xref: /petsc/src/mat/interface/matrix.c (revision 5d8720fa41fb4169420198de95a3fb9ffc339d07)
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   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAssemblyEnd()");
929   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
930   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
931   PetscFunctionReturn(PETSC_SUCCESS);
932 }
933 
934 /*@
935   MatSetUp - Sets up the internal matrix data structures for later use by the matrix
936 
937   Collective
938 
939   Input Parameter:
940 . A - the matrix
941 
942   Level: advanced
943 
944   Notes:
945   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
946   setting values in the matrix.
947 
948   This routine is called internally by other `Mat` functions when needed so rarely needs to be called by users
949 
950 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
951 @*/
952 PetscErrorCode MatSetUp(Mat A)
953 {
954   PetscFunctionBegin;
955   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
956   if (!((PetscObject)A)->type_name) {
957     PetscMPIInt size;
958 
959     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
960     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
961   }
962   if (!A->preallocated) PetscTryTypeMethod(A, setup);
963   PetscCall(PetscLayoutSetUp(A->rmap));
964   PetscCall(PetscLayoutSetUp(A->cmap));
965   A->preallocated = PETSC_TRUE;
966   PetscFunctionReturn(PETSC_SUCCESS);
967 }
968 
969 #if defined(PETSC_HAVE_SAWS)
970   #include <petscviewersaws.h>
971 #endif
972 
973 /*
974    If threadsafety is on extraneous matrices may be printed
975 
976    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
977 */
978 #if !defined(PETSC_HAVE_THREADSAFETY)
979 static PetscInt insidematview = 0;
980 #endif
981 
982 /*@
983   MatViewFromOptions - View properties of the matrix based on options set in the options database
984 
985   Collective
986 
987   Input Parameters:
988 + A    - the matrix
989 . obj  - optional additional object that provides the options prefix to use
990 - name - command line option
991 
992   Options Database Key:
993 . -mat_view [viewertype]:... - the viewer and its options
994 
995   Level: intermediate
996 
997   Note:
998 .vb
999     If no value is provided ascii:stdout is used
1000        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
1001                                                   for example ascii::ascii_info prints just the information about the object not all details
1002                                                   unless :append is given filename opens in write mode, overwriting what was already there
1003        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1004        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1005        socket[:port]                             defaults to the standard output port
1006        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1007 .ve
1008 
1009 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1010 @*/
1011 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1012 {
1013   PetscFunctionBegin;
1014   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1015 #if !defined(PETSC_HAVE_THREADSAFETY)
1016   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1017 #endif
1018   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1019   PetscFunctionReturn(PETSC_SUCCESS);
1020 }
1021 
1022 /*@
1023   MatView - display information about a matrix in a variety ways
1024 
1025   Collective on viewer
1026 
1027   Input Parameters:
1028 + mat    - the matrix
1029 - viewer - visualization context
1030 
1031   Options Database Keys:
1032 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1033 . -mat_view ::ascii_info_detail    - Prints more detailed info
1034 . -mat_view                        - Prints matrix in ASCII format
1035 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1036 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1037 . -display <name>                  - Sets display name (default is host)
1038 . -draw_pause <sec>                - Sets number of seconds to pause after display
1039 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1040 . -viewer_socket_machine <machine> - -
1041 . -viewer_socket_port <port>       - -
1042 . -mat_view binary                 - save matrix to file in binary format
1043 - -viewer_binary_filename <name>   - -
1044 
1045   Level: beginner
1046 
1047   Notes:
1048   The available visualization contexts include
1049 +    `PETSC_VIEWER_STDOUT_SELF`   - for sequential matrices
1050 .    `PETSC_VIEWER_STDOUT_WORLD`  - for parallel matrices created on `PETSC_COMM_WORLD`
1051 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1052 -     `PETSC_VIEWER_DRAW_WORLD`   - graphical display of nonzero structure
1053 
1054   The user can open alternative visualization contexts with
1055 +    `PetscViewerASCIIOpen()`  - Outputs matrix to a specified file
1056 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a  specified file; corresponding input uses `MatLoad()`
1057 .    `PetscViewerDrawOpen()`   - Outputs nonzero matrix nonzero structure to an X window display
1058 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer, `PETSCVIEWERSOCKET`. Only the `MATSEQDENSE` and `MATAIJ` types support this viewer.
1059 
1060   The user can call `PetscViewerPushFormat()` to specify the output
1061   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1062   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1063 +    `PETSC_VIEWER_DEFAULT`           - default, prints matrix contents
1064 .    `PETSC_VIEWER_ASCII_MATLAB`      - prints matrix contents in MATLAB format
1065 .    `PETSC_VIEWER_ASCII_DENSE`       - prints entire matrix including zeros
1066 .    `PETSC_VIEWER_ASCII_COMMON`      - prints matrix contents, using a sparse  format common among all matrix types
1067 .    `PETSC_VIEWER_ASCII_IMPL`        - prints matrix contents, using an implementation-specific format (which is in many cases the same as the default)
1068 .    `PETSC_VIEWER_ASCII_INFO`        - prints basic information about the matrix size and structure (not the matrix entries)
1069 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about the matrix nonzero structure (still not vector or matrix entries)
1070 
1071   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1072   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1073 
1074   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1075 
1076   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1077   viewer is used.
1078 
1079   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1080   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1081 
1082   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1083   and then use the following mouse functions.
1084 .vb
1085   left mouse: zoom in
1086   middle mouse: zoom out
1087   right mouse: continue with the simulation
1088 .ve
1089 
1090 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1091           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1092 @*/
1093 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1094 {
1095   PetscInt          rows, cols, rbs, cbs;
1096   PetscBool         isascii, isstring, issaws;
1097   PetscViewerFormat format;
1098   PetscMPIInt       size;
1099 
1100   PetscFunctionBegin;
1101   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1102   PetscValidType(mat, 1);
1103   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1104   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1105 
1106   PetscCall(PetscViewerGetFormat(viewer, &format));
1107   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1108   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1109 
1110 #if !defined(PETSC_HAVE_THREADSAFETY)
1111   insidematview++;
1112 #endif
1113   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1114   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1115   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1116   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");
1117 
1118   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1119   if (isascii) {
1120     if (!mat->preallocated) {
1121       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1122 #if !defined(PETSC_HAVE_THREADSAFETY)
1123       insidematview--;
1124 #endif
1125       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1126       PetscFunctionReturn(PETSC_SUCCESS);
1127     }
1128     if (!mat->assembled) {
1129       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1130 #if !defined(PETSC_HAVE_THREADSAFETY)
1131       insidematview--;
1132 #endif
1133       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1134       PetscFunctionReturn(PETSC_SUCCESS);
1135     }
1136     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1137     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1138       MatNullSpace nullsp, transnullsp;
1139 
1140       PetscCall(PetscViewerASCIIPushTab(viewer));
1141       PetscCall(MatGetSize(mat, &rows, &cols));
1142       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1143       if (rbs != 1 || cbs != 1) {
1144         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" : ""));
1145         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1146       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1147       if (mat->factortype) {
1148         MatSolverType solver;
1149         PetscCall(MatFactorGetSolverType(mat, &solver));
1150         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1151       }
1152       if (mat->ops->getinfo) {
1153         MatInfo info;
1154         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1155         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1156         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1157       }
1158       PetscCall(MatGetNullSpace(mat, &nullsp));
1159       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1160       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1161       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1162       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1163       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1164       PetscCall(PetscViewerASCIIPushTab(viewer));
1165       PetscCall(MatProductView(mat, viewer));
1166       PetscCall(PetscViewerASCIIPopTab(viewer));
1167       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1168         IS tmp;
1169 
1170         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1171         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1172         PetscCall(PetscViewerASCIIPushTab(viewer));
1173         PetscCall(ISView(tmp, viewer));
1174         PetscCall(PetscViewerASCIIPopTab(viewer));
1175         PetscCall(ISDestroy(&tmp));
1176       }
1177     }
1178   } else if (issaws) {
1179 #if defined(PETSC_HAVE_SAWS)
1180     PetscMPIInt rank;
1181 
1182     PetscCall(PetscObjectName((PetscObject)mat));
1183     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1184     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1185 #endif
1186   } else if (isstring) {
1187     const char *type;
1188     PetscCall(MatGetType(mat, &type));
1189     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1190     PetscTryTypeMethod(mat, view, viewer);
1191   }
1192   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1193     PetscCall(PetscViewerASCIIPushTab(viewer));
1194     PetscUseTypeMethod(mat, viewnative, viewer);
1195     PetscCall(PetscViewerASCIIPopTab(viewer));
1196   } else if (mat->ops->view) {
1197     PetscCall(PetscViewerASCIIPushTab(viewer));
1198     PetscUseTypeMethod(mat, view, viewer);
1199     PetscCall(PetscViewerASCIIPopTab(viewer));
1200   }
1201   if (isascii) {
1202     PetscCall(PetscViewerGetFormat(viewer, &format));
1203     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1204   }
1205   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1206 #if !defined(PETSC_HAVE_THREADSAFETY)
1207   insidematview--;
1208 #endif
1209   PetscFunctionReturn(PETSC_SUCCESS);
1210 }
1211 
1212 #if defined(PETSC_USE_DEBUG)
1213   #include <../src/sys/totalview/tv_data_display.h>
1214 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1215 {
1216   TV_add_row("Local rows", "int", &mat->rmap->n);
1217   TV_add_row("Local columns", "int", &mat->cmap->n);
1218   TV_add_row("Global rows", "int", &mat->rmap->N);
1219   TV_add_row("Global columns", "int", &mat->cmap->N);
1220   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1221   return TV_format_OK;
1222 }
1223 #endif
1224 
1225 /*@
1226   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1227   with `MatView()`.  The matrix format is determined from the options database.
1228   Generates a parallel MPI matrix if the communicator has more than one
1229   processor.  The default matrix type is `MATAIJ`.
1230 
1231   Collective
1232 
1233   Input Parameters:
1234 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1235             or some related function before a call to `MatLoad()`
1236 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1237 
1238   Options Database Key:
1239 . -matload_block_size <bs> - set block size
1240 
1241   Level: beginner
1242 
1243   Notes:
1244   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1245   `Mat` before calling this routine if you wish to set it from the options database.
1246 
1247   `MatLoad()` automatically loads into the options database any options
1248   given in the file filename.info where filename is the name of the file
1249   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1250   file will be ignored if you use the -viewer_binary_skip_info option.
1251 
1252   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1253   sets the default matrix type AIJ and sets the local and global sizes.
1254   If type and/or size is already set, then the same are used.
1255 
1256   In parallel, each processor can load a subset of rows (or the
1257   entire matrix).  This routine is especially useful when a large
1258   matrix is stored on disk and only part of it is desired on each
1259   processor.  For example, a parallel solver may access only some of
1260   the rows from each processor.  The algorithm used here reads
1261   relatively small blocks of data rather than reading the entire
1262   matrix and then subsetting it.
1263 
1264   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1265   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1266   or the sequence like
1267 .vb
1268     `PetscViewer` v;
1269     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1270     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1271     `PetscViewerSetFromOptions`(v);
1272     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1273     `PetscViewerFileSetName`(v,"datafile");
1274 .ve
1275   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1276 $ -viewer_type {binary, hdf5}
1277 
1278   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1279   and src/mat/tutorials/ex10.c with the second approach.
1280 
1281   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1282   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1283   Multiple objects, both matrices and vectors, can be stored within the same file.
1284   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1285 
1286   Most users should not need to know the details of the binary storage
1287   format, since `MatLoad()` and `MatView()` completely hide these details.
1288   But for anyone who is interested, the standard binary matrix storage
1289   format is
1290 
1291 .vb
1292     PetscInt    MAT_FILE_CLASSID
1293     PetscInt    number of rows
1294     PetscInt    number of columns
1295     PetscInt    total number of nonzeros
1296     PetscInt    *number nonzeros in each row
1297     PetscInt    *column indices of all nonzeros (starting index is zero)
1298     PetscScalar *values of all nonzeros
1299 .ve
1300   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1301   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
1302   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1303 
1304   PETSc automatically does the byte swapping for
1305   machines that store the bytes reversed. Thus if you write your own binary
1306   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1307   and `PetscBinaryWrite()` to see how this may be done.
1308 
1309   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1310   Each processor's chunk is loaded independently by its owning MPI process.
1311   Multiple objects, both matrices and vectors, can be stored within the same file.
1312   They are looked up by their PetscObject name.
1313 
1314   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1315   by default the same structure and naming of the AIJ arrays and column count
1316   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1317 $    save example.mat A b -v7.3
1318   can be directly read by this routine (see Reference 1 for details).
1319 
1320   Depending on your MATLAB version, this format might be a default,
1321   otherwise you can set it as default in Preferences.
1322 
1323   Unless -nocompression flag is used to save the file in MATLAB,
1324   PETSc must be configured with ZLIB package.
1325 
1326   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1327 
1328   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1329 
1330   Corresponding `MatView()` is not yet implemented.
1331 
1332   The loaded matrix is actually a transpose of the original one in MATLAB,
1333   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1334   With this format, matrix is automatically transposed by PETSc,
1335   unless the matrix is marked as SPD or symmetric
1336   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1337 
1338   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1339 
1340 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1341  @*/
1342 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1343 {
1344   PetscBool flg;
1345 
1346   PetscFunctionBegin;
1347   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1348   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1349 
1350   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1351 
1352   flg = PETSC_FALSE;
1353   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1354   if (flg) {
1355     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1356     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1357   }
1358   flg = PETSC_FALSE;
1359   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1360   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1361 
1362   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1363   PetscUseTypeMethod(mat, load, viewer);
1364   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1365   PetscFunctionReturn(PETSC_SUCCESS);
1366 }
1367 
1368 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1369 {
1370   Mat_Redundant *redund = *redundant;
1371 
1372   PetscFunctionBegin;
1373   if (redund) {
1374     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1375       PetscCall(ISDestroy(&redund->isrow));
1376       PetscCall(ISDestroy(&redund->iscol));
1377       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1378     } else {
1379       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1380       PetscCall(PetscFree(redund->sbuf_j));
1381       PetscCall(PetscFree(redund->sbuf_a));
1382       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1383         PetscCall(PetscFree(redund->rbuf_j[i]));
1384         PetscCall(PetscFree(redund->rbuf_a[i]));
1385       }
1386       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1387     }
1388 
1389     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1390     PetscCall(PetscFree(redund));
1391   }
1392   PetscFunctionReturn(PETSC_SUCCESS);
1393 }
1394 
1395 /*@
1396   MatDestroy - Frees space taken by a matrix.
1397 
1398   Collective
1399 
1400   Input Parameter:
1401 . A - the matrix
1402 
1403   Level: beginner
1404 
1405   Developer Note:
1406   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1407   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1408   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1409   if changes are needed here.
1410 
1411 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1412 @*/
1413 PetscErrorCode MatDestroy(Mat *A)
1414 {
1415   PetscFunctionBegin;
1416   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1417   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1418   if (--((PetscObject)*A)->refct > 0) {
1419     *A = NULL;
1420     PetscFunctionReturn(PETSC_SUCCESS);
1421   }
1422 
1423   /* if memory was published with SAWs then destroy it */
1424   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1425   PetscTryTypeMethod(*A, destroy);
1426 
1427   PetscCall(PetscFree((*A)->factorprefix));
1428   PetscCall(PetscFree((*A)->defaultvectype));
1429   PetscCall(PetscFree((*A)->defaultrandtype));
1430   PetscCall(PetscFree((*A)->bsizes));
1431   PetscCall(PetscFree((*A)->solvertype));
1432   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1433   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1434   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1435   PetscCall(MatProductClear(*A));
1436   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1437   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1438   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1439   PetscCall(MatDestroy(&(*A)->schur));
1440   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1441   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1442   PetscCall(PetscHeaderDestroy(A));
1443   PetscFunctionReturn(PETSC_SUCCESS);
1444 }
1445 
1446 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1447 /*@
1448   MatSetValues - Inserts or adds a block of values into a matrix.
1449   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1450   MUST be called after all calls to `MatSetValues()` have been completed.
1451 
1452   Not Collective
1453 
1454   Input Parameters:
1455 + mat  - the matrix
1456 . v    - a logically two-dimensional array of values
1457 . m    - the number of rows
1458 . idxm - the global indices of the rows
1459 . n    - the number of columns
1460 . idxn - the global indices of the columns
1461 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1462 
1463   Level: beginner
1464 
1465   Notes:
1466   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1467 
1468   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1469   options cannot be mixed without intervening calls to the assembly
1470   routines.
1471 
1472   `MatSetValues()` uses 0-based row and column numbers in Fortran
1473   as well as in C.
1474 
1475   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1476   simply ignored. This allows easily inserting element stiffness matrices
1477   with homogeneous Dirichlet boundary conditions that you don't want represented
1478   in the matrix.
1479 
1480   Efficiency Alert:
1481   The routine `MatSetValuesBlocked()` may offer much better efficiency
1482   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1483 
1484   Fortran Notes:
1485   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1486 .vb
1487   MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
1488 .ve
1489 
1490   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1491 
1492   Developer Note:
1493   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1494   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1495 
1496 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1497           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1498 @*/
1499 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1500 {
1501   PetscFunctionBeginHot;
1502   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1503   PetscValidType(mat, 1);
1504   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1505   PetscAssertPointer(idxm, 3);
1506   PetscAssertPointer(idxn, 5);
1507   MatCheckPreallocated(mat, 1);
1508 
1509   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1510   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1511 
1512   if (PetscDefined(USE_DEBUG)) {
1513     PetscInt i, j;
1514 
1515     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1516     if (v) {
1517       for (i = 0; i < m; i++) {
1518         for (j = 0; j < n; j++) {
1519           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1520 #if defined(PETSC_USE_COMPLEX)
1521             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]);
1522 #else
1523             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]);
1524 #endif
1525         }
1526       }
1527     }
1528     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);
1529     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);
1530   }
1531 
1532   if (mat->assembled) {
1533     mat->was_assembled = PETSC_TRUE;
1534     mat->assembled     = PETSC_FALSE;
1535   }
1536   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1537   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1538   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1539   PetscFunctionReturn(PETSC_SUCCESS);
1540 }
1541 
1542 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1543 /*@
1544   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1545   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1546   MUST be called after all calls to `MatSetValues()` have been completed.
1547 
1548   Not Collective
1549 
1550   Input Parameters:
1551 + mat  - the matrix
1552 . v    - a logically two-dimensional array of values
1553 . ism  - the rows to provide
1554 . isn  - the columns to provide
1555 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1556 
1557   Level: beginner
1558 
1559   Notes:
1560   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1561 
1562   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1563   options cannot be mixed without intervening calls to the assembly
1564   routines.
1565 
1566   `MatSetValues()` uses 0-based row and column numbers in Fortran
1567   as well as in C.
1568 
1569   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1570   simply ignored. This allows easily inserting element stiffness matrices
1571   with homogeneous Dirichlet boundary conditions that you don't want represented
1572   in the matrix.
1573 
1574   Efficiency Alert:
1575   The routine `MatSetValuesBlocked()` may offer much better efficiency
1576   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1577 
1578   This is currently not optimized for any particular `ISType`
1579 
1580   Developer Note:
1581   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1582   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1583 
1584 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1585           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1586 @*/
1587 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1588 {
1589   PetscInt        m, n;
1590   const PetscInt *rows, *cols;
1591 
1592   PetscFunctionBeginHot;
1593   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1594   PetscCall(ISGetIndices(ism, &rows));
1595   PetscCall(ISGetIndices(isn, &cols));
1596   PetscCall(ISGetLocalSize(ism, &m));
1597   PetscCall(ISGetLocalSize(isn, &n));
1598   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1599   PetscCall(ISRestoreIndices(ism, &rows));
1600   PetscCall(ISRestoreIndices(isn, &cols));
1601   PetscFunctionReturn(PETSC_SUCCESS);
1602 }
1603 
1604 /*@
1605   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1606   values into a matrix
1607 
1608   Not Collective
1609 
1610   Input Parameters:
1611 + mat - the matrix
1612 . row - the (block) row to set
1613 - v   - a logically two-dimensional array of values
1614 
1615   Level: intermediate
1616 
1617   Notes:
1618   The values, `v`, are column-oriented (for the block version) and sorted
1619 
1620   All the nonzero values in `row` must be provided
1621 
1622   The matrix must have previously had its column indices set, likely by having been assembled.
1623 
1624   `row` must belong to this MPI process
1625 
1626 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1627           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1628 @*/
1629 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1630 {
1631   PetscInt globalrow;
1632 
1633   PetscFunctionBegin;
1634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1635   PetscValidType(mat, 1);
1636   PetscAssertPointer(v, 3);
1637   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1638   PetscCall(MatSetValuesRow(mat, globalrow, v));
1639   PetscFunctionReturn(PETSC_SUCCESS);
1640 }
1641 
1642 /*@
1643   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1644   values into a matrix
1645 
1646   Not Collective
1647 
1648   Input Parameters:
1649 + mat - the matrix
1650 . row - the (block) row to set
1651 - 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
1652 
1653   Level: advanced
1654 
1655   Notes:
1656   The values, `v`, are column-oriented for the block version.
1657 
1658   All the nonzeros in `row` must be provided
1659 
1660   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1661 
1662   `row` must belong to this process
1663 
1664 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1665           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1666 @*/
1667 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1668 {
1669   PetscFunctionBeginHot;
1670   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1671   PetscValidType(mat, 1);
1672   MatCheckPreallocated(mat, 1);
1673   PetscAssertPointer(v, 3);
1674   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1675   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1676   mat->insertmode = INSERT_VALUES;
1677 
1678   if (mat->assembled) {
1679     mat->was_assembled = PETSC_TRUE;
1680     mat->assembled     = PETSC_FALSE;
1681   }
1682   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1683   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1684   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1685   PetscFunctionReturn(PETSC_SUCCESS);
1686 }
1687 
1688 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1689 /*@
1690   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1691   Using structured grid indexing
1692 
1693   Not Collective
1694 
1695   Input Parameters:
1696 + mat  - the matrix
1697 . m    - number of rows being entered
1698 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1699 . n    - number of columns being entered
1700 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1701 . v    - a logically two-dimensional array of values
1702 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1703 
1704   Level: beginner
1705 
1706   Notes:
1707   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1708 
1709   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1710   options cannot be mixed without intervening calls to the assembly
1711   routines.
1712 
1713   The grid coordinates are across the entire grid, not just the local portion
1714 
1715   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1716   as well as in C.
1717 
1718   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1719 
1720   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1721   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1722 
1723   The columns and rows in the stencil passed in MUST be contained within the
1724   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1725   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1726   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1727   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1728 
1729   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1730   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1731   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1732   `DM_BOUNDARY_PERIODIC` boundary type.
1733 
1734   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
1735   a single value per point) you can skip filling those indices.
1736 
1737   Inspired by the structured grid interface to the HYPRE package
1738   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1739 
1740   Efficiency Alert:
1741   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1742   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1743 
1744   Fortran Note:
1745   `idxm` and `idxn` should be declared as
1746 $     MatStencil idxm(4,m),idxn(4,n)
1747   and the values inserted using
1748 .vb
1749     idxm(MatStencil_i,1) = i
1750     idxm(MatStencil_j,1) = j
1751     idxm(MatStencil_k,1) = k
1752     idxm(MatStencil_c,1) = c
1753     etc
1754 .ve
1755 
1756 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1757           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1758 @*/
1759 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1760 {
1761   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1762   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1763   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1764 
1765   PetscFunctionBegin;
1766   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1767   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1768   PetscValidType(mat, 1);
1769   PetscAssertPointer(idxm, 3);
1770   PetscAssertPointer(idxn, 5);
1771 
1772   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1773     jdxm = buf;
1774     jdxn = buf + m;
1775   } else {
1776     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1777     jdxm = bufm;
1778     jdxn = bufn;
1779   }
1780   for (i = 0; i < m; i++) {
1781     for (j = 0; j < 3 - sdim; j++) dxm++;
1782     tmp = *dxm++ - starts[0];
1783     for (j = 0; j < dim - 1; j++) {
1784       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1785       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1786     }
1787     if (mat->stencil.noc) dxm++;
1788     jdxm[i] = tmp;
1789   }
1790   for (i = 0; i < n; i++) {
1791     for (j = 0; j < 3 - sdim; j++) dxn++;
1792     tmp = *dxn++ - starts[0];
1793     for (j = 0; j < dim - 1; j++) {
1794       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1795       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1796     }
1797     if (mat->stencil.noc) dxn++;
1798     jdxn[i] = tmp;
1799   }
1800   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1801   PetscCall(PetscFree2(bufm, bufn));
1802   PetscFunctionReturn(PETSC_SUCCESS);
1803 }
1804 
1805 /*@
1806   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1807   Using structured grid indexing
1808 
1809   Not Collective
1810 
1811   Input Parameters:
1812 + mat  - the matrix
1813 . m    - number of rows being entered
1814 . idxm - grid coordinates for matrix rows being entered
1815 . n    - number of columns being entered
1816 . idxn - grid coordinates for matrix columns being entered
1817 . v    - a logically two-dimensional array of values
1818 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1819 
1820   Level: beginner
1821 
1822   Notes:
1823   By default the values, `v`, are row-oriented and unsorted.
1824   See `MatSetOption()` for other options.
1825 
1826   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1827   options cannot be mixed without intervening calls to the assembly
1828   routines.
1829 
1830   The grid coordinates are across the entire grid, not just the local portion
1831 
1832   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1833   as well as in C.
1834 
1835   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1836 
1837   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1838   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1839 
1840   The columns and rows in the stencil passed in MUST be contained within the
1841   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1842   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1843   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1844   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1845 
1846   Negative indices may be passed in idxm and idxn, these rows and columns are
1847   simply ignored. This allows easily inserting element stiffness matrices
1848   with homogeneous Dirichlet boundary conditions that you don't want represented
1849   in the matrix.
1850 
1851   Inspired by the structured grid interface to the HYPRE package
1852   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1853 
1854   Fortran Note:
1855   `idxm` and `idxn` should be declared as
1856 $     MatStencil idxm(4,m),idxn(4,n)
1857   and the values inserted using
1858 .vb
1859     idxm(MatStencil_i,1) = i
1860     idxm(MatStencil_j,1) = j
1861     idxm(MatStencil_k,1) = k
1862    etc
1863 .ve
1864 
1865 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1866           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1867           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1868 @*/
1869 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1870 {
1871   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1872   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1873   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1874 
1875   PetscFunctionBegin;
1876   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1878   PetscValidType(mat, 1);
1879   PetscAssertPointer(idxm, 3);
1880   PetscAssertPointer(idxn, 5);
1881   PetscAssertPointer(v, 6);
1882 
1883   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1884     jdxm = buf;
1885     jdxn = buf + m;
1886   } else {
1887     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1888     jdxm = bufm;
1889     jdxn = bufn;
1890   }
1891   for (i = 0; i < m; i++) {
1892     for (j = 0; j < 3 - sdim; j++) dxm++;
1893     tmp = *dxm++ - starts[0];
1894     for (j = 0; j < sdim - 1; j++) {
1895       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1896       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1897     }
1898     dxm++;
1899     jdxm[i] = tmp;
1900   }
1901   for (i = 0; i < n; i++) {
1902     for (j = 0; j < 3 - sdim; j++) dxn++;
1903     tmp = *dxn++ - starts[0];
1904     for (j = 0; j < sdim - 1; j++) {
1905       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1906       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1907     }
1908     dxn++;
1909     jdxn[i] = tmp;
1910   }
1911   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1912   PetscCall(PetscFree2(bufm, bufn));
1913   PetscFunctionReturn(PETSC_SUCCESS);
1914 }
1915 
1916 /*@
1917   MatSetStencil - Sets the grid information for setting values into a matrix via
1918   `MatSetValuesStencil()`
1919 
1920   Not Collective
1921 
1922   Input Parameters:
1923 + mat    - the matrix
1924 . dim    - dimension of the grid 1, 2, or 3
1925 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1926 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1927 - dof    - number of degrees of freedom per node
1928 
1929   Level: beginner
1930 
1931   Notes:
1932   Inspired by the structured grid interface to the HYPRE package
1933   (www.llnl.gov/CASC/hyper)
1934 
1935   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1936   user.
1937 
1938 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1939           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1940 @*/
1941 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1942 {
1943   PetscFunctionBegin;
1944   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1945   PetscAssertPointer(dims, 3);
1946   PetscAssertPointer(starts, 4);
1947 
1948   mat->stencil.dim = dim + (dof > 1);
1949   for (PetscInt i = 0; i < dim; i++) {
1950     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1951     mat->stencil.starts[i] = starts[dim - i - 1];
1952   }
1953   mat->stencil.dims[dim]   = dof;
1954   mat->stencil.starts[dim] = 0;
1955   mat->stencil.noc         = (PetscBool)(dof == 1);
1956   PetscFunctionReturn(PETSC_SUCCESS);
1957 }
1958 
1959 /*@
1960   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1961 
1962   Not Collective
1963 
1964   Input Parameters:
1965 + mat  - the matrix
1966 . v    - a logically two-dimensional array of values
1967 . m    - the number of block rows
1968 . idxm - the global block indices
1969 . n    - the number of block columns
1970 . idxn - the global block indices
1971 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1972 
1973   Level: intermediate
1974 
1975   Notes:
1976   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1977   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1978 
1979   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1980   NOT the total number of rows/columns; for example, if the block size is 2 and
1981   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
1982   The values in `idxm` would be 1 2; that is the first index for each block divided by
1983   the block size.
1984 
1985   You must call `MatSetBlockSize()` when constructing this matrix (before
1986   preallocating it).
1987 
1988   By default the values, `v`, are row-oriented, so the layout of
1989   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1990 
1991   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1992   options cannot be mixed without intervening calls to the assembly
1993   routines.
1994 
1995   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1996   as well as in C.
1997 
1998   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1999   simply ignored. This allows easily inserting element stiffness matrices
2000   with homogeneous Dirichlet boundary conditions that you don't want represented
2001   in the matrix.
2002 
2003   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2004   internal searching must be done to determine where to place the
2005   data in the matrix storage space.  By instead inserting blocks of
2006   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2007   reduced.
2008 
2009   Example:
2010 .vb
2011    Suppose m=n=2 and block size(bs) = 2 The array is
2012 
2013    1  2  | 3  4
2014    5  6  | 7  8
2015    - - - | - - -
2016    9  10 | 11 12
2017    13 14 | 15 16
2018 
2019    v[] should be passed in like
2020    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2021 
2022   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2023    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2024 .ve
2025 
2026   Fortran Notes:
2027   If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2028 .vb
2029   MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
2030 .ve
2031 
2032   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2033 
2034 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2035 @*/
2036 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2037 {
2038   PetscFunctionBeginHot;
2039   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2040   PetscValidType(mat, 1);
2041   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2042   PetscAssertPointer(idxm, 3);
2043   PetscAssertPointer(idxn, 5);
2044   MatCheckPreallocated(mat, 1);
2045   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2046   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2047   if (PetscDefined(USE_DEBUG)) {
2048     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2049     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2050   }
2051   if (PetscDefined(USE_DEBUG)) {
2052     PetscInt rbs, cbs, M, N, i;
2053     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2054     PetscCall(MatGetSize(mat, &M, &N));
2055     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);
2056     for (i = 0; i < n; i++)
2057       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);
2058   }
2059   if (mat->assembled) {
2060     mat->was_assembled = PETSC_TRUE;
2061     mat->assembled     = PETSC_FALSE;
2062   }
2063   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2064   if (mat->ops->setvaluesblocked) {
2065     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2066   } else {
2067     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2068     PetscInt i, j, bs, cbs;
2069 
2070     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2071     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2072       iidxm = buf;
2073       iidxn = buf + m * bs;
2074     } else {
2075       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2076       iidxm = bufr;
2077       iidxn = bufc;
2078     }
2079     for (i = 0; i < m; i++) {
2080       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2081     }
2082     if (m != n || bs != cbs || idxm != idxn) {
2083       for (i = 0; i < n; i++) {
2084         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2085       }
2086     } else iidxn = iidxm;
2087     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2088     PetscCall(PetscFree2(bufr, bufc));
2089   }
2090   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2091   PetscFunctionReturn(PETSC_SUCCESS);
2092 }
2093 
2094 /*@
2095   MatGetValues - Gets a block of local values from a matrix.
2096 
2097   Not Collective; can only return values that are owned by the give process
2098 
2099   Input Parameters:
2100 + mat  - the matrix
2101 . v    - a logically two-dimensional array for storing the values
2102 . m    - the number of rows
2103 . idxm - the  global indices of the rows
2104 . n    - the number of columns
2105 - idxn - the global indices of the columns
2106 
2107   Level: advanced
2108 
2109   Notes:
2110   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2111   The values, `v`, are then returned in a row-oriented format,
2112   analogous to that used by default in `MatSetValues()`.
2113 
2114   `MatGetValues()` uses 0-based row and column numbers in
2115   Fortran as well as in C.
2116 
2117   `MatGetValues()` requires that the matrix has been assembled
2118   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2119   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2120   without intermediate matrix assembly.
2121 
2122   Negative row or column indices will be ignored and those locations in `v` will be
2123   left unchanged.
2124 
2125   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2126   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2127   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2128 
2129 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2130 @*/
2131 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2132 {
2133   PetscFunctionBegin;
2134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2135   PetscValidType(mat, 1);
2136   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2137   PetscAssertPointer(idxm, 3);
2138   PetscAssertPointer(idxn, 5);
2139   PetscAssertPointer(v, 6);
2140   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2141   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2142   MatCheckPreallocated(mat, 1);
2143 
2144   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2145   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2146   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2147   PetscFunctionReturn(PETSC_SUCCESS);
2148 }
2149 
2150 /*@
2151   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2152   defined previously by `MatSetLocalToGlobalMapping()`
2153 
2154   Not Collective
2155 
2156   Input Parameters:
2157 + mat  - the matrix
2158 . nrow - number of rows
2159 . irow - the row local indices
2160 . ncol - number of columns
2161 - icol - the column local indices
2162 
2163   Output Parameter:
2164 . y - a logically two-dimensional array of values
2165 
2166   Level: advanced
2167 
2168   Notes:
2169   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2170 
2171   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,
2172   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2173   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2174   with `MatSetLocalToGlobalMapping()`.
2175 
2176   Developer Note:
2177   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2178   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2179 
2180 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2181           `MatSetValuesLocal()`, `MatGetValues()`
2182 @*/
2183 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2184 {
2185   PetscFunctionBeginHot;
2186   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2187   PetscValidType(mat, 1);
2188   MatCheckPreallocated(mat, 1);
2189   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2190   PetscAssertPointer(irow, 3);
2191   PetscAssertPointer(icol, 5);
2192   if (PetscDefined(USE_DEBUG)) {
2193     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2194     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2195   }
2196   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2197   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2198   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2199   else {
2200     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2201     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2202       irowm = buf;
2203       icolm = buf + nrow;
2204     } else {
2205       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2206       irowm = bufr;
2207       icolm = bufc;
2208     }
2209     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2210     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2211     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2212     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2213     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2214     PetscCall(PetscFree2(bufr, bufc));
2215   }
2216   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2217   PetscFunctionReturn(PETSC_SUCCESS);
2218 }
2219 
2220 /*@
2221   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2222   the same size. Currently, this can only be called once and creates the given matrix.
2223 
2224   Not Collective
2225 
2226   Input Parameters:
2227 + mat  - the matrix
2228 . nb   - the number of blocks
2229 . bs   - the number of rows (and columns) in each block
2230 . rows - a concatenation of the rows for each block
2231 - v    - a concatenation of logically two-dimensional arrays of values
2232 
2233   Level: advanced
2234 
2235   Notes:
2236   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2237 
2238   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2239 
2240 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2241           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2242 @*/
2243 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2244 {
2245   PetscFunctionBegin;
2246   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2247   PetscValidType(mat, 1);
2248   PetscAssertPointer(rows, 4);
2249   PetscAssertPointer(v, 5);
2250   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2251 
2252   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2253   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2254   else {
2255     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2256   }
2257   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2258   PetscFunctionReturn(PETSC_SUCCESS);
2259 }
2260 
2261 /*@
2262   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2263   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2264   using a local (per-processor) numbering.
2265 
2266   Not Collective
2267 
2268   Input Parameters:
2269 + x        - the matrix
2270 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2271 - cmapping - column mapping
2272 
2273   Level: intermediate
2274 
2275   Note:
2276   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2277 
2278 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2279 @*/
2280 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2281 {
2282   PetscFunctionBegin;
2283   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2284   PetscValidType(x, 1);
2285   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2286   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2287   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2288   else {
2289     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2290     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2291   }
2292   PetscFunctionReturn(PETSC_SUCCESS);
2293 }
2294 
2295 /*@
2296   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2297 
2298   Not Collective
2299 
2300   Input Parameter:
2301 . A - the matrix
2302 
2303   Output Parameters:
2304 + rmapping - row mapping
2305 - cmapping - column mapping
2306 
2307   Level: advanced
2308 
2309 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2310 @*/
2311 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2312 {
2313   PetscFunctionBegin;
2314   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2315   PetscValidType(A, 1);
2316   if (rmapping) {
2317     PetscAssertPointer(rmapping, 2);
2318     *rmapping = A->rmap->mapping;
2319   }
2320   if (cmapping) {
2321     PetscAssertPointer(cmapping, 3);
2322     *cmapping = A->cmap->mapping;
2323   }
2324   PetscFunctionReturn(PETSC_SUCCESS);
2325 }
2326 
2327 /*@
2328   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2329 
2330   Logically Collective
2331 
2332   Input Parameters:
2333 + A    - the matrix
2334 . rmap - row layout
2335 - cmap - column layout
2336 
2337   Level: advanced
2338 
2339   Note:
2340   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2341 
2342 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2343 @*/
2344 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2345 {
2346   PetscFunctionBegin;
2347   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2348   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2349   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2350   PetscFunctionReturn(PETSC_SUCCESS);
2351 }
2352 
2353 /*@
2354   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2355 
2356   Not Collective
2357 
2358   Input Parameter:
2359 . A - the matrix
2360 
2361   Output Parameters:
2362 + rmap - row layout
2363 - cmap - column layout
2364 
2365   Level: advanced
2366 
2367 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2368 @*/
2369 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2370 {
2371   PetscFunctionBegin;
2372   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2373   PetscValidType(A, 1);
2374   if (rmap) {
2375     PetscAssertPointer(rmap, 2);
2376     *rmap = A->rmap;
2377   }
2378   if (cmap) {
2379     PetscAssertPointer(cmap, 3);
2380     *cmap = A->cmap;
2381   }
2382   PetscFunctionReturn(PETSC_SUCCESS);
2383 }
2384 
2385 /*@
2386   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2387   using a local numbering of the rows and columns.
2388 
2389   Not Collective
2390 
2391   Input Parameters:
2392 + mat  - the matrix
2393 . nrow - number of rows
2394 . irow - the row local indices
2395 . ncol - number of columns
2396 . icol - the column local indices
2397 . y    - a logically two-dimensional array of values
2398 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2399 
2400   Level: intermediate
2401 
2402   Notes:
2403   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2404 
2405   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2406   options cannot be mixed without intervening calls to the assembly
2407   routines.
2408 
2409   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2410   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2411 
2412   Fortran Notes:
2413   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2414 .vb
2415   MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2416 .ve
2417 
2418   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2419 
2420   Developer Note:
2421   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2422   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2423 
2424 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2425           `MatGetValuesLocal()`
2426 @*/
2427 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2428 {
2429   PetscFunctionBeginHot;
2430   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2431   PetscValidType(mat, 1);
2432   MatCheckPreallocated(mat, 1);
2433   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2434   PetscAssertPointer(irow, 3);
2435   PetscAssertPointer(icol, 5);
2436   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2437   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2438   if (PetscDefined(USE_DEBUG)) {
2439     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2440     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2441   }
2442 
2443   if (mat->assembled) {
2444     mat->was_assembled = PETSC_TRUE;
2445     mat->assembled     = PETSC_FALSE;
2446   }
2447   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2448   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2449   else {
2450     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2451     const PetscInt *irowm, *icolm;
2452 
2453     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2454       bufr  = buf;
2455       bufc  = buf + nrow;
2456       irowm = bufr;
2457       icolm = bufc;
2458     } else {
2459       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2460       irowm = bufr;
2461       icolm = bufc;
2462     }
2463     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2464     else irowm = irow;
2465     if (mat->cmap->mapping) {
2466       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2467         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2468       } else icolm = irowm;
2469     } else icolm = icol;
2470     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2471     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2472   }
2473   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2474   PetscFunctionReturn(PETSC_SUCCESS);
2475 }
2476 
2477 /*@
2478   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2479   using a local ordering of the nodes a block at a time.
2480 
2481   Not Collective
2482 
2483   Input Parameters:
2484 + mat  - the matrix
2485 . nrow - number of rows
2486 . irow - the row local indices
2487 . ncol - number of columns
2488 . icol - the column local indices
2489 . y    - a logically two-dimensional array of values
2490 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2491 
2492   Level: intermediate
2493 
2494   Notes:
2495   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2496   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2497 
2498   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2499   options cannot be mixed without intervening calls to the assembly
2500   routines.
2501 
2502   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2503   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2504 
2505   Fortran Notes:
2506   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2507 .vb
2508   MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2509 .ve
2510 
2511   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2512 
2513   Developer Note:
2514   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2515   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2516 
2517 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2518           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2519 @*/
2520 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2521 {
2522   PetscFunctionBeginHot;
2523   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2524   PetscValidType(mat, 1);
2525   MatCheckPreallocated(mat, 1);
2526   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2527   PetscAssertPointer(irow, 3);
2528   PetscAssertPointer(icol, 5);
2529   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2530   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2531   if (PetscDefined(USE_DEBUG)) {
2532     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2533     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);
2534   }
2535 
2536   if (mat->assembled) {
2537     mat->was_assembled = PETSC_TRUE;
2538     mat->assembled     = PETSC_FALSE;
2539   }
2540   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2541     PetscInt irbs, rbs;
2542     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2543     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2544     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2545   }
2546   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2547     PetscInt icbs, cbs;
2548     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2549     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2550     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2551   }
2552   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2553   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2554   else {
2555     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2556     const PetscInt *irowm, *icolm;
2557 
2558     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2559       bufr  = buf;
2560       bufc  = buf + nrow;
2561       irowm = bufr;
2562       icolm = bufc;
2563     } else {
2564       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2565       irowm = bufr;
2566       icolm = bufc;
2567     }
2568     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2569     else irowm = irow;
2570     if (mat->cmap->mapping) {
2571       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2572         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2573       } else icolm = irowm;
2574     } else icolm = icol;
2575     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2576     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2577   }
2578   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2579   PetscFunctionReturn(PETSC_SUCCESS);
2580 }
2581 
2582 /*@
2583   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2584 
2585   Collective
2586 
2587   Input Parameters:
2588 + mat - the matrix
2589 - x   - the vector to be multiplied
2590 
2591   Output Parameter:
2592 . y - the result
2593 
2594   Level: developer
2595 
2596   Note:
2597   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2598   call `MatMultDiagonalBlock`(A,y,y).
2599 
2600 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2601 @*/
2602 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2603 {
2604   PetscFunctionBegin;
2605   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2606   PetscValidType(mat, 1);
2607   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2608   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2609 
2610   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2611   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2612   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2613   MatCheckPreallocated(mat, 1);
2614 
2615   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2616   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2617   PetscFunctionReturn(PETSC_SUCCESS);
2618 }
2619 
2620 /*@
2621   MatMult - Computes the matrix-vector product, $y = Ax$.
2622 
2623   Neighbor-wise Collective
2624 
2625   Input Parameters:
2626 + mat - the matrix
2627 - x   - the vector to be multiplied
2628 
2629   Output Parameter:
2630 . y - the result
2631 
2632   Level: beginner
2633 
2634   Note:
2635   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2636   call `MatMult`(A,y,y).
2637 
2638 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2639 @*/
2640 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2641 {
2642   PetscFunctionBegin;
2643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2644   PetscValidType(mat, 1);
2645   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2646   VecCheckAssembled(x);
2647   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2648   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2649   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2650   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2651   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);
2652   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);
2653   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);
2654   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);
2655   PetscCall(VecSetErrorIfLocked(y, 3));
2656   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2657   MatCheckPreallocated(mat, 1);
2658 
2659   PetscCall(VecLockReadPush(x));
2660   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2661   PetscUseTypeMethod(mat, mult, x, y);
2662   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2663   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2664   PetscCall(VecLockReadPop(x));
2665   PetscFunctionReturn(PETSC_SUCCESS);
2666 }
2667 
2668 /*@
2669   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2670 
2671   Neighbor-wise Collective
2672 
2673   Input Parameters:
2674 + mat - the matrix
2675 - x   - the vector to be multiplied
2676 
2677   Output Parameter:
2678 . y - the result
2679 
2680   Level: beginner
2681 
2682   Notes:
2683   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2684   call `MatMultTranspose`(A,y,y).
2685 
2686   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2687   use `MatMultHermitianTranspose()`
2688 
2689 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2690 @*/
2691 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2692 {
2693   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2694 
2695   PetscFunctionBegin;
2696   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2697   PetscValidType(mat, 1);
2698   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2699   VecCheckAssembled(x);
2700   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2701 
2702   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2703   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2704   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2705   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);
2706   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);
2707   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);
2708   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);
2709   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2710   MatCheckPreallocated(mat, 1);
2711 
2712   if (!mat->ops->multtranspose) {
2713     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2714     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);
2715   } else op = mat->ops->multtranspose;
2716   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2717   PetscCall(VecLockReadPush(x));
2718   PetscCall((*op)(mat, x, y));
2719   PetscCall(VecLockReadPop(x));
2720   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2721   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2722   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2723   PetscFunctionReturn(PETSC_SUCCESS);
2724 }
2725 
2726 /*@
2727   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2728 
2729   Neighbor-wise Collective
2730 
2731   Input Parameters:
2732 + mat - the matrix
2733 - x   - the vector to be multiplied
2734 
2735   Output Parameter:
2736 . y - the result
2737 
2738   Level: beginner
2739 
2740   Notes:
2741   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2742   call `MatMultHermitianTranspose`(A,y,y).
2743 
2744   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2745 
2746   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2747 
2748 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2749 @*/
2750 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2751 {
2752   PetscFunctionBegin;
2753   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2754   PetscValidType(mat, 1);
2755   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2756   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2757 
2758   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2759   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2760   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2761   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);
2762   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);
2763   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);
2764   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);
2765   MatCheckPreallocated(mat, 1);
2766 
2767   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2768 #if defined(PETSC_USE_COMPLEX)
2769   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2770     PetscCall(VecLockReadPush(x));
2771     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2772     else PetscUseTypeMethod(mat, mult, x, y);
2773     PetscCall(VecLockReadPop(x));
2774   } else {
2775     Vec w;
2776     PetscCall(VecDuplicate(x, &w));
2777     PetscCall(VecCopy(x, w));
2778     PetscCall(VecConjugate(w));
2779     PetscCall(MatMultTranspose(mat, w, y));
2780     PetscCall(VecDestroy(&w));
2781     PetscCall(VecConjugate(y));
2782   }
2783   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2784 #else
2785   PetscCall(MatMultTranspose(mat, x, y));
2786 #endif
2787   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2788   PetscFunctionReturn(PETSC_SUCCESS);
2789 }
2790 
2791 /*@
2792   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2793 
2794   Neighbor-wise Collective
2795 
2796   Input Parameters:
2797 + mat - the matrix
2798 . v1  - the vector to be multiplied by `mat`
2799 - v2  - the vector to be added to the result
2800 
2801   Output Parameter:
2802 . v3 - the result
2803 
2804   Level: beginner
2805 
2806   Note:
2807   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2808   call `MatMultAdd`(A,v1,v2,v1).
2809 
2810 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2811 @*/
2812 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2813 {
2814   PetscFunctionBegin;
2815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2816   PetscValidType(mat, 1);
2817   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2818   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2819   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2820 
2821   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2822   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2823   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);
2824   /* 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);
2825      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); */
2826   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);
2827   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);
2828   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2829   MatCheckPreallocated(mat, 1);
2830 
2831   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2832   PetscCall(VecLockReadPush(v1));
2833   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2834   PetscCall(VecLockReadPop(v1));
2835   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2836   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2837   PetscFunctionReturn(PETSC_SUCCESS);
2838 }
2839 
2840 /*@
2841   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2842 
2843   Neighbor-wise Collective
2844 
2845   Input Parameters:
2846 + mat - the matrix
2847 . v1  - the vector to be multiplied by the transpose of the matrix
2848 - v2  - the vector to be added to the result
2849 
2850   Output Parameter:
2851 . v3 - the result
2852 
2853   Level: beginner
2854 
2855   Note:
2856   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2857   call `MatMultTransposeAdd`(A,v1,v2,v1).
2858 
2859 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2860 @*/
2861 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2862 {
2863   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2864 
2865   PetscFunctionBegin;
2866   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2867   PetscValidType(mat, 1);
2868   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2869   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2870   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2871 
2872   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2873   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2874   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);
2875   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);
2876   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);
2877   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2878   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2879   MatCheckPreallocated(mat, 1);
2880 
2881   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2882   PetscCall(VecLockReadPush(v1));
2883   PetscCall((*op)(mat, v1, v2, v3));
2884   PetscCall(VecLockReadPop(v1));
2885   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2886   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2887   PetscFunctionReturn(PETSC_SUCCESS);
2888 }
2889 
2890 /*@
2891   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2892 
2893   Neighbor-wise Collective
2894 
2895   Input Parameters:
2896 + mat - the matrix
2897 . v1  - the vector to be multiplied by the Hermitian transpose
2898 - v2  - the vector to be added to the result
2899 
2900   Output Parameter:
2901 . v3 - the result
2902 
2903   Level: beginner
2904 
2905   Note:
2906   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2907   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2908 
2909 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2910 @*/
2911 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2912 {
2913   PetscFunctionBegin;
2914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2915   PetscValidType(mat, 1);
2916   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2917   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2918   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2919 
2920   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2921   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2922   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2923   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);
2924   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);
2925   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);
2926   MatCheckPreallocated(mat, 1);
2927 
2928   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2929   PetscCall(VecLockReadPush(v1));
2930   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2931   else {
2932     Vec w, z;
2933     PetscCall(VecDuplicate(v1, &w));
2934     PetscCall(VecCopy(v1, w));
2935     PetscCall(VecConjugate(w));
2936     PetscCall(VecDuplicate(v3, &z));
2937     PetscCall(MatMultTranspose(mat, w, z));
2938     PetscCall(VecDestroy(&w));
2939     PetscCall(VecConjugate(z));
2940     if (v2 != v3) {
2941       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2942     } else {
2943       PetscCall(VecAXPY(v3, 1.0, z));
2944     }
2945     PetscCall(VecDestroy(&z));
2946   }
2947   PetscCall(VecLockReadPop(v1));
2948   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2949   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2950   PetscFunctionReturn(PETSC_SUCCESS);
2951 }
2952 
2953 /*@
2954   MatGetFactorType - gets the type of factorization a matrix is
2955 
2956   Not Collective
2957 
2958   Input Parameter:
2959 . mat - the matrix
2960 
2961   Output Parameter:
2962 . 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`
2963 
2964   Level: intermediate
2965 
2966 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2967           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2968 @*/
2969 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2970 {
2971   PetscFunctionBegin;
2972   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2973   PetscValidType(mat, 1);
2974   PetscAssertPointer(t, 2);
2975   *t = mat->factortype;
2976   PetscFunctionReturn(PETSC_SUCCESS);
2977 }
2978 
2979 /*@
2980   MatSetFactorType - sets the type of factorization a matrix is
2981 
2982   Logically Collective
2983 
2984   Input Parameters:
2985 + mat - the matrix
2986 - 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`
2987 
2988   Level: intermediate
2989 
2990 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2991           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2992 @*/
2993 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2994 {
2995   PetscFunctionBegin;
2996   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2997   PetscValidType(mat, 1);
2998   mat->factortype = t;
2999   PetscFunctionReturn(PETSC_SUCCESS);
3000 }
3001 
3002 /*@
3003   MatGetInfo - Returns information about matrix storage (number of
3004   nonzeros, memory, etc.).
3005 
3006   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3007 
3008   Input Parameters:
3009 + mat  - the matrix
3010 - 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)
3011 
3012   Output Parameter:
3013 . info - matrix information context
3014 
3015   Options Database Key:
3016 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3017 
3018   Level: intermediate
3019 
3020   Notes:
3021   The `MatInfo` context contains a variety of matrix data, including
3022   number of nonzeros allocated and used, number of mallocs during
3023   matrix assembly, etc.  Additional information for factored matrices
3024   is provided (such as the fill ratio, number of mallocs during
3025   factorization, etc.).
3026 
3027   Example:
3028   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3029   data within the `MatInfo` context.  For example,
3030 .vb
3031       MatInfo info;
3032       Mat     A;
3033       double  mal, nz_a, nz_u;
3034 
3035       MatGetInfo(A, MAT_LOCAL, &info);
3036       mal  = info.mallocs;
3037       nz_a = info.nz_allocated;
3038 .ve
3039 
3040   Fortran Note:
3041   Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters
3042   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
3043   a complete list of parameter names.
3044 .vb
3045       MatInfo info(MAT_INFO_SIZE)
3046       double  precision mal, nz_a
3047       Mat     A
3048       integer ierr
3049 
3050       call MatGetInfo(A, MAT_LOCAL, info, ierr)
3051       mal = info(MAT_INFO_MALLOCS)
3052       nz_a = info(MAT_INFO_NZ_ALLOCATED)
3053 .ve
3054 
3055 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3056 @*/
3057 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3058 {
3059   PetscFunctionBegin;
3060   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3061   PetscValidType(mat, 1);
3062   PetscAssertPointer(info, 3);
3063   MatCheckPreallocated(mat, 1);
3064   PetscUseTypeMethod(mat, getinfo, flag, info);
3065   PetscFunctionReturn(PETSC_SUCCESS);
3066 }
3067 
3068 /*
3069    This is used by external packages where it is not easy to get the info from the actual
3070    matrix factorization.
3071 */
3072 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3073 {
3074   PetscFunctionBegin;
3075   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3076   PetscFunctionReturn(PETSC_SUCCESS);
3077 }
3078 
3079 /*@
3080   MatLUFactor - Performs in-place LU factorization of matrix.
3081 
3082   Collective
3083 
3084   Input Parameters:
3085 + mat  - the matrix
3086 . row  - row permutation
3087 . col  - column permutation
3088 - info - options for factorization, includes
3089 .vb
3090           fill - expected fill as ratio of original fill.
3091           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3092                    Run with the option -info to determine an optimal value to use
3093 .ve
3094 
3095   Level: developer
3096 
3097   Notes:
3098   Most users should employ the `KSP` interface for linear solvers
3099   instead of working directly with matrix algebra routines such as this.
3100   See, e.g., `KSPCreate()`.
3101 
3102   This changes the state of the matrix to a factored matrix; it cannot be used
3103   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3104 
3105   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3106   when not using `KSP`.
3107 
3108   Developer Note:
3109   The Fortran interface is not autogenerated as the
3110   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3111 
3112 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3113           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3114 @*/
3115 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3116 {
3117   MatFactorInfo tinfo;
3118 
3119   PetscFunctionBegin;
3120   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3121   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3122   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3123   if (info) PetscAssertPointer(info, 4);
3124   PetscValidType(mat, 1);
3125   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3126   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3127   MatCheckPreallocated(mat, 1);
3128   if (!info) {
3129     PetscCall(MatFactorInfoInitialize(&tinfo));
3130     info = &tinfo;
3131   }
3132 
3133   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3134   PetscUseTypeMethod(mat, lufactor, row, col, info);
3135   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3136   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3137   PetscFunctionReturn(PETSC_SUCCESS);
3138 }
3139 
3140 /*@
3141   MatILUFactor - Performs in-place ILU factorization of matrix.
3142 
3143   Collective
3144 
3145   Input Parameters:
3146 + mat  - the matrix
3147 . row  - row permutation
3148 . col  - column permutation
3149 - info - structure containing
3150 .vb
3151       levels - number of levels of fill.
3152       expected fill - as ratio of original fill.
3153       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3154                 missing diagonal entries)
3155 .ve
3156 
3157   Level: developer
3158 
3159   Notes:
3160   Most users should employ the `KSP` interface for linear solvers
3161   instead of working directly with matrix algebra routines such as this.
3162   See, e.g., `KSPCreate()`.
3163 
3164   Probably really in-place only when level of fill is zero, otherwise allocates
3165   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3166   when not using `KSP`.
3167 
3168   Developer Note:
3169   The Fortran interface is not autogenerated as the
3170   interface definition cannot be generated correctly [due to MatFactorInfo]
3171 
3172 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3173 @*/
3174 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3175 {
3176   PetscFunctionBegin;
3177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3178   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3179   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3180   PetscAssertPointer(info, 4);
3181   PetscValidType(mat, 1);
3182   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3183   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3184   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3185   MatCheckPreallocated(mat, 1);
3186 
3187   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3188   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3189   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3190   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3191   PetscFunctionReturn(PETSC_SUCCESS);
3192 }
3193 
3194 /*@
3195   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3196   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3197 
3198   Collective
3199 
3200   Input Parameters:
3201 + fact - the factor matrix obtained with `MatGetFactor()`
3202 . mat  - the matrix
3203 . row  - the row permutation
3204 . col  - the column permutation
3205 - info - options for factorization, includes
3206 .vb
3207           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3208           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3209 .ve
3210 
3211   Level: developer
3212 
3213   Notes:
3214   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3215 
3216   Most users should employ the simplified `KSP` interface for linear solvers
3217   instead of working directly with matrix algebra routines such as this.
3218   See, e.g., `KSPCreate()`.
3219 
3220   Developer Note:
3221   The Fortran interface is not autogenerated as the
3222   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3223 
3224 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3225 @*/
3226 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3227 {
3228   MatFactorInfo tinfo;
3229 
3230   PetscFunctionBegin;
3231   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3232   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3233   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3234   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3235   if (info) PetscAssertPointer(info, 5);
3236   PetscValidType(fact, 1);
3237   PetscValidType(mat, 2);
3238   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3239   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3240   MatCheckPreallocated(mat, 2);
3241   if (!info) {
3242     PetscCall(MatFactorInfoInitialize(&tinfo));
3243     info = &tinfo;
3244   }
3245 
3246   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3247   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3248   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3249   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3250   PetscFunctionReturn(PETSC_SUCCESS);
3251 }
3252 
3253 /*@
3254   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3255   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3256 
3257   Collective
3258 
3259   Input Parameters:
3260 + fact - the factor matrix obtained with `MatGetFactor()`
3261 . mat  - the matrix
3262 - info - options for factorization
3263 
3264   Level: developer
3265 
3266   Notes:
3267   See `MatLUFactor()` for in-place factorization.  See
3268   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3269 
3270   Most users should employ the `KSP` interface for linear solvers
3271   instead of working directly with matrix algebra routines such as this.
3272   See, e.g., `KSPCreate()`.
3273 
3274   Developer Note:
3275   The Fortran interface is not autogenerated as the
3276   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3277 
3278 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3279 @*/
3280 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3281 {
3282   MatFactorInfo tinfo;
3283 
3284   PetscFunctionBegin;
3285   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3286   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3287   PetscValidType(fact, 1);
3288   PetscValidType(mat, 2);
3289   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3290   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,
3291              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3292 
3293   MatCheckPreallocated(mat, 2);
3294   if (!info) {
3295     PetscCall(MatFactorInfoInitialize(&tinfo));
3296     info = &tinfo;
3297   }
3298 
3299   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3300   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3301   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3302   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3303   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3304   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3305   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3306   PetscFunctionReturn(PETSC_SUCCESS);
3307 }
3308 
3309 /*@
3310   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3311   symmetric matrix.
3312 
3313   Collective
3314 
3315   Input Parameters:
3316 + mat  - the matrix
3317 . perm - row and column permutations
3318 - info - expected fill as ratio of original fill
3319 
3320   Level: developer
3321 
3322   Notes:
3323   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3324   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3325 
3326   Most users should employ the `KSP` interface for linear solvers
3327   instead of working directly with matrix algebra routines such as this.
3328   See, e.g., `KSPCreate()`.
3329 
3330   Developer Note:
3331   The Fortran interface is not autogenerated as the
3332   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3333 
3334 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3335           `MatGetOrdering()`
3336 @*/
3337 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3338 {
3339   MatFactorInfo tinfo;
3340 
3341   PetscFunctionBegin;
3342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3343   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3344   if (info) PetscAssertPointer(info, 3);
3345   PetscValidType(mat, 1);
3346   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3347   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3348   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3349   MatCheckPreallocated(mat, 1);
3350   if (!info) {
3351     PetscCall(MatFactorInfoInitialize(&tinfo));
3352     info = &tinfo;
3353   }
3354 
3355   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3356   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3357   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3358   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3359   PetscFunctionReturn(PETSC_SUCCESS);
3360 }
3361 
3362 /*@
3363   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3364   of a symmetric matrix.
3365 
3366   Collective
3367 
3368   Input Parameters:
3369 + fact - the factor matrix obtained with `MatGetFactor()`
3370 . mat  - the matrix
3371 . perm - row and column permutations
3372 - info - options for factorization, includes
3373 .vb
3374           fill - expected fill as ratio of original fill.
3375           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3376                    Run with the option -info to determine an optimal value to use
3377 .ve
3378 
3379   Level: developer
3380 
3381   Notes:
3382   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3383   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3384 
3385   Most users should employ the `KSP` interface for linear solvers
3386   instead of working directly with matrix algebra routines such as this.
3387   See, e.g., `KSPCreate()`.
3388 
3389   Developer Note:
3390   The Fortran interface is not autogenerated as the
3391   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3392 
3393 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3394           `MatGetOrdering()`
3395 @*/
3396 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3397 {
3398   MatFactorInfo tinfo;
3399 
3400   PetscFunctionBegin;
3401   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3403   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3404   if (info) PetscAssertPointer(info, 4);
3405   PetscValidType(fact, 1);
3406   PetscValidType(mat, 2);
3407   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3408   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3409   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3410   MatCheckPreallocated(mat, 2);
3411   if (!info) {
3412     PetscCall(MatFactorInfoInitialize(&tinfo));
3413     info = &tinfo;
3414   }
3415 
3416   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3417   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3418   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3419   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3420   PetscFunctionReturn(PETSC_SUCCESS);
3421 }
3422 
3423 /*@
3424   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3425   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3426   `MatCholeskyFactorSymbolic()`.
3427 
3428   Collective
3429 
3430   Input Parameters:
3431 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3432 . mat  - the initial matrix that is to be factored
3433 - info - options for factorization
3434 
3435   Level: developer
3436 
3437   Note:
3438   Most users should employ the `KSP` interface for linear solvers
3439   instead of working directly with matrix algebra routines such as this.
3440   See, e.g., `KSPCreate()`.
3441 
3442   Developer Note:
3443   The Fortran interface is not autogenerated as the
3444   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3445 
3446 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3447 @*/
3448 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3449 {
3450   MatFactorInfo tinfo;
3451 
3452   PetscFunctionBegin;
3453   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3454   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3455   PetscValidType(fact, 1);
3456   PetscValidType(mat, 2);
3457   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3458   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,
3459              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3460   MatCheckPreallocated(mat, 2);
3461   if (!info) {
3462     PetscCall(MatFactorInfoInitialize(&tinfo));
3463     info = &tinfo;
3464   }
3465 
3466   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3467   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3468   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3469   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3470   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3471   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3472   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3473   PetscFunctionReturn(PETSC_SUCCESS);
3474 }
3475 
3476 /*@
3477   MatQRFactor - Performs in-place QR factorization of matrix.
3478 
3479   Collective
3480 
3481   Input Parameters:
3482 + mat  - the matrix
3483 . col  - column permutation
3484 - info - options for factorization, includes
3485 .vb
3486           fill - expected fill as ratio of original fill.
3487           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3488                    Run with the option -info to determine an optimal value to use
3489 .ve
3490 
3491   Level: developer
3492 
3493   Notes:
3494   Most users should employ the `KSP` interface for linear solvers
3495   instead of working directly with matrix algebra routines such as this.
3496   See, e.g., `KSPCreate()`.
3497 
3498   This changes the state of the matrix to a factored matrix; it cannot be used
3499   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3500 
3501   Developer Note:
3502   The Fortran interface is not autogenerated as the
3503   interface definition cannot be generated correctly [due to MatFactorInfo]
3504 
3505 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3506           `MatSetUnfactored()`
3507 @*/
3508 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3509 {
3510   PetscFunctionBegin;
3511   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3512   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3513   if (info) PetscAssertPointer(info, 3);
3514   PetscValidType(mat, 1);
3515   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3516   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3517   MatCheckPreallocated(mat, 1);
3518   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3519   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3520   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3521   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3522   PetscFunctionReturn(PETSC_SUCCESS);
3523 }
3524 
3525 /*@
3526   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3527   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3528 
3529   Collective
3530 
3531   Input Parameters:
3532 + fact - the factor matrix obtained with `MatGetFactor()`
3533 . mat  - the matrix
3534 . col  - column permutation
3535 - info - options for factorization, includes
3536 .vb
3537           fill - expected fill as ratio of original fill.
3538           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3539                    Run with the option -info to determine an optimal value to use
3540 .ve
3541 
3542   Level: developer
3543 
3544   Note:
3545   Most users should employ the `KSP` interface for linear solvers
3546   instead of working directly with matrix algebra routines such as this.
3547   See, e.g., `KSPCreate()`.
3548 
3549   Developer Note:
3550   The Fortran interface is not autogenerated as the
3551   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3552 
3553 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3554 @*/
3555 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3556 {
3557   MatFactorInfo tinfo;
3558 
3559   PetscFunctionBegin;
3560   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3561   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3562   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3563   if (info) PetscAssertPointer(info, 4);
3564   PetscValidType(fact, 1);
3565   PetscValidType(mat, 2);
3566   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3567   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3568   MatCheckPreallocated(mat, 2);
3569   if (!info) {
3570     PetscCall(MatFactorInfoInitialize(&tinfo));
3571     info = &tinfo;
3572   }
3573 
3574   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3575   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3576   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3577   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3578   PetscFunctionReturn(PETSC_SUCCESS);
3579 }
3580 
3581 /*@
3582   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3583   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3584 
3585   Collective
3586 
3587   Input Parameters:
3588 + fact - the factor matrix obtained with `MatGetFactor()`
3589 . mat  - the matrix
3590 - info - options for factorization
3591 
3592   Level: developer
3593 
3594   Notes:
3595   See `MatQRFactor()` for in-place factorization.
3596 
3597   Most users should employ the `KSP` interface for linear solvers
3598   instead of working directly with matrix algebra routines such as this.
3599   See, e.g., `KSPCreate()`.
3600 
3601   Developer Note:
3602   The Fortran interface is not autogenerated as the
3603   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3604 
3605 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3606 @*/
3607 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3608 {
3609   MatFactorInfo tinfo;
3610 
3611   PetscFunctionBegin;
3612   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3613   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3614   PetscValidType(fact, 1);
3615   PetscValidType(mat, 2);
3616   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3617   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,
3618              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3619 
3620   MatCheckPreallocated(mat, 2);
3621   if (!info) {
3622     PetscCall(MatFactorInfoInitialize(&tinfo));
3623     info = &tinfo;
3624   }
3625 
3626   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3627   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3628   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3629   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3630   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3631   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3632   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3633   PetscFunctionReturn(PETSC_SUCCESS);
3634 }
3635 
3636 /*@
3637   MatSolve - Solves $A x = b$, given a factored matrix.
3638 
3639   Neighbor-wise Collective
3640 
3641   Input Parameters:
3642 + mat - the factored matrix
3643 - b   - the right-hand-side vector
3644 
3645   Output Parameter:
3646 . x - the result vector
3647 
3648   Level: developer
3649 
3650   Notes:
3651   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3652   call `MatSolve`(A,x,x).
3653 
3654   Most users should employ the `KSP` interface for linear solvers
3655   instead of working directly with matrix algebra routines such as this.
3656   See, e.g., `KSPCreate()`.
3657 
3658 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3659 @*/
3660 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3661 {
3662   PetscFunctionBegin;
3663   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3664   PetscValidType(mat, 1);
3665   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3666   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3667   PetscCheckSameComm(mat, 1, b, 2);
3668   PetscCheckSameComm(mat, 1, x, 3);
3669   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3670   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);
3671   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);
3672   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);
3673   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3674   MatCheckPreallocated(mat, 1);
3675 
3676   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3677   PetscCall(VecFlag(x, mat->factorerrortype));
3678   if (mat->factorerrortype) {
3679     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3680   } else PetscUseTypeMethod(mat, solve, b, x);
3681   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3682   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3683   PetscFunctionReturn(PETSC_SUCCESS);
3684 }
3685 
3686 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3687 {
3688   Vec      b, x;
3689   PetscInt N, i;
3690   PetscErrorCode (*f)(Mat, Vec, Vec);
3691   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3692 
3693   PetscFunctionBegin;
3694   if (A->factorerrortype) {
3695     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3696     PetscCall(MatSetInf(X));
3697     PetscFunctionReturn(PETSC_SUCCESS);
3698   }
3699   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3700   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3701   PetscCall(MatBoundToCPU(A, &Abound));
3702   if (!Abound) {
3703     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3704     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3705   }
3706 #if PetscDefined(HAVE_CUDA)
3707   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3708   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3709 #elif PetscDefined(HAVE_HIP)
3710   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3711   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3712 #endif
3713   PetscCall(MatGetSize(B, NULL, &N));
3714   for (i = 0; i < N; i++) {
3715     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3716     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3717     PetscCall((*f)(A, b, x));
3718     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3719     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3720   }
3721   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3722   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3723   PetscFunctionReturn(PETSC_SUCCESS);
3724 }
3725 
3726 /*@
3727   MatMatSolve - Solves $A X = B$, given a factored matrix.
3728 
3729   Neighbor-wise Collective
3730 
3731   Input Parameters:
3732 + A - the factored matrix
3733 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3734 
3735   Output Parameter:
3736 . X - the result matrix (dense matrix)
3737 
3738   Level: developer
3739 
3740   Note:
3741   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3742   otherwise, `B` and `X` cannot be the same.
3743 
3744 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3745 @*/
3746 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3747 {
3748   PetscFunctionBegin;
3749   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3750   PetscValidType(A, 1);
3751   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3752   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3753   PetscCheckSameComm(A, 1, B, 2);
3754   PetscCheckSameComm(A, 1, X, 3);
3755   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);
3756   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);
3757   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");
3758   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3759   MatCheckPreallocated(A, 1);
3760 
3761   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3762   if (!A->ops->matsolve) {
3763     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3764     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3765   } else PetscUseTypeMethod(A, matsolve, B, X);
3766   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3767   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3768   PetscFunctionReturn(PETSC_SUCCESS);
3769 }
3770 
3771 /*@
3772   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3773 
3774   Neighbor-wise Collective
3775 
3776   Input Parameters:
3777 + A - the factored matrix
3778 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3779 
3780   Output Parameter:
3781 . X - the result matrix (dense matrix)
3782 
3783   Level: developer
3784 
3785   Note:
3786   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3787   call `MatMatSolveTranspose`(A,X,X).
3788 
3789 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3790 @*/
3791 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3792 {
3793   PetscFunctionBegin;
3794   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3795   PetscValidType(A, 1);
3796   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3797   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3798   PetscCheckSameComm(A, 1, B, 2);
3799   PetscCheckSameComm(A, 1, X, 3);
3800   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3801   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);
3802   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);
3803   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);
3804   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");
3805   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3806   MatCheckPreallocated(A, 1);
3807 
3808   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3809   if (!A->ops->matsolvetranspose) {
3810     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3811     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3812   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3813   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3814   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3815   PetscFunctionReturn(PETSC_SUCCESS);
3816 }
3817 
3818 /*@
3819   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3820 
3821   Neighbor-wise Collective
3822 
3823   Input Parameters:
3824 + A  - the factored matrix
3825 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3826 
3827   Output Parameter:
3828 . X - the result matrix (dense matrix)
3829 
3830   Level: developer
3831 
3832   Note:
3833   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
3834   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3835 
3836 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3837 @*/
3838 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3839 {
3840   PetscFunctionBegin;
3841   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3842   PetscValidType(A, 1);
3843   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3844   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3845   PetscCheckSameComm(A, 1, Bt, 2);
3846   PetscCheckSameComm(A, 1, X, 3);
3847 
3848   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3849   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);
3850   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);
3851   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");
3852   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3853   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3854   MatCheckPreallocated(A, 1);
3855 
3856   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3857   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3858   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3859   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3860   PetscFunctionReturn(PETSC_SUCCESS);
3861 }
3862 
3863 /*@
3864   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3865   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3866 
3867   Neighbor-wise Collective
3868 
3869   Input Parameters:
3870 + mat - the factored matrix
3871 - b   - the right-hand-side vector
3872 
3873   Output Parameter:
3874 . x - the result vector
3875 
3876   Level: developer
3877 
3878   Notes:
3879   `MatSolve()` should be used for most applications, as it performs
3880   a forward solve followed by a backward solve.
3881 
3882   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3883   call `MatForwardSolve`(A,x,x).
3884 
3885   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3886   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3887   `MatForwardSolve()` solves $U^T*D y = b$, and
3888   `MatBackwardSolve()` solves $U x = y$.
3889   Thus they do not provide a symmetric preconditioner.
3890 
3891 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3892 @*/
3893 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3894 {
3895   PetscFunctionBegin;
3896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3897   PetscValidType(mat, 1);
3898   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3899   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3900   PetscCheckSameComm(mat, 1, b, 2);
3901   PetscCheckSameComm(mat, 1, x, 3);
3902   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3903   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);
3904   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);
3905   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);
3906   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3907   MatCheckPreallocated(mat, 1);
3908 
3909   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3910   PetscUseTypeMethod(mat, forwardsolve, b, x);
3911   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3912   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3913   PetscFunctionReturn(PETSC_SUCCESS);
3914 }
3915 
3916 /*@
3917   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3918   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3919 
3920   Neighbor-wise Collective
3921 
3922   Input Parameters:
3923 + mat - the factored matrix
3924 - b   - the right-hand-side vector
3925 
3926   Output Parameter:
3927 . x - the result vector
3928 
3929   Level: developer
3930 
3931   Notes:
3932   `MatSolve()` should be used for most applications, as it performs
3933   a forward solve followed by a backward solve.
3934 
3935   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3936   call `MatBackwardSolve`(A,x,x).
3937 
3938   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3939   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3940   `MatForwardSolve()` solves $U^T*D y = b$, and
3941   `MatBackwardSolve()` solves $U x = y$.
3942   Thus they do not provide a symmetric preconditioner.
3943 
3944 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3945 @*/
3946 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3947 {
3948   PetscFunctionBegin;
3949   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3950   PetscValidType(mat, 1);
3951   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3952   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3953   PetscCheckSameComm(mat, 1, b, 2);
3954   PetscCheckSameComm(mat, 1, x, 3);
3955   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3956   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);
3957   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);
3958   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);
3959   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3960   MatCheckPreallocated(mat, 1);
3961 
3962   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3963   PetscUseTypeMethod(mat, backwardsolve, b, x);
3964   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3965   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3966   PetscFunctionReturn(PETSC_SUCCESS);
3967 }
3968 
3969 /*@
3970   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3971 
3972   Neighbor-wise Collective
3973 
3974   Input Parameters:
3975 + mat - the factored matrix
3976 . b   - the right-hand-side vector
3977 - y   - the vector to be added to
3978 
3979   Output Parameter:
3980 . x - the result vector
3981 
3982   Level: developer
3983 
3984   Note:
3985   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3986   call `MatSolveAdd`(A,x,y,x).
3987 
3988 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3989 @*/
3990 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3991 {
3992   PetscScalar one = 1.0;
3993   Vec         tmp;
3994 
3995   PetscFunctionBegin;
3996   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3997   PetscValidType(mat, 1);
3998   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3999   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4000   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4001   PetscCheckSameComm(mat, 1, b, 2);
4002   PetscCheckSameComm(mat, 1, y, 3);
4003   PetscCheckSameComm(mat, 1, x, 4);
4004   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4005   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);
4006   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);
4007   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);
4008   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);
4009   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);
4010   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4011   MatCheckPreallocated(mat, 1);
4012 
4013   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4014   PetscCall(VecFlag(x, mat->factorerrortype));
4015   if (mat->factorerrortype) {
4016     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4017   } else if (mat->ops->solveadd) {
4018     PetscUseTypeMethod(mat, solveadd, b, y, x);
4019   } else {
4020     /* do the solve then the add manually */
4021     if (x != y) {
4022       PetscCall(MatSolve(mat, b, x));
4023       PetscCall(VecAXPY(x, one, y));
4024     } else {
4025       PetscCall(VecDuplicate(x, &tmp));
4026       PetscCall(VecCopy(x, tmp));
4027       PetscCall(MatSolve(mat, b, x));
4028       PetscCall(VecAXPY(x, one, tmp));
4029       PetscCall(VecDestroy(&tmp));
4030     }
4031   }
4032   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4033   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4034   PetscFunctionReturn(PETSC_SUCCESS);
4035 }
4036 
4037 /*@
4038   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4039 
4040   Neighbor-wise Collective
4041 
4042   Input Parameters:
4043 + mat - the factored matrix
4044 - b   - the right-hand-side vector
4045 
4046   Output Parameter:
4047 . x - the result vector
4048 
4049   Level: developer
4050 
4051   Notes:
4052   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4053   call `MatSolveTranspose`(A,x,x).
4054 
4055   Most users should employ the `KSP` interface for linear solvers
4056   instead of working directly with matrix algebra routines such as this.
4057   See, e.g., `KSPCreate()`.
4058 
4059 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4060 @*/
4061 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4062 {
4063   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4064 
4065   PetscFunctionBegin;
4066   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4067   PetscValidType(mat, 1);
4068   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4069   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4070   PetscCheckSameComm(mat, 1, b, 2);
4071   PetscCheckSameComm(mat, 1, x, 3);
4072   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4073   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);
4074   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);
4075   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4076   MatCheckPreallocated(mat, 1);
4077   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4078   PetscCall(VecFlag(x, mat->factorerrortype));
4079   if (mat->factorerrortype) {
4080     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4081   } else {
4082     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4083     PetscCall((*f)(mat, b, x));
4084   }
4085   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4086   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4087   PetscFunctionReturn(PETSC_SUCCESS);
4088 }
4089 
4090 /*@
4091   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4092   factored matrix.
4093 
4094   Neighbor-wise Collective
4095 
4096   Input Parameters:
4097 + mat - the factored matrix
4098 . b   - the right-hand-side vector
4099 - y   - the vector to be added to
4100 
4101   Output Parameter:
4102 . x - the result vector
4103 
4104   Level: developer
4105 
4106   Note:
4107   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4108   call `MatSolveTransposeAdd`(A,x,y,x).
4109 
4110 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4111 @*/
4112 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4113 {
4114   PetscScalar one = 1.0;
4115   Vec         tmp;
4116   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4117 
4118   PetscFunctionBegin;
4119   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4120   PetscValidType(mat, 1);
4121   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4122   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4123   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4124   PetscCheckSameComm(mat, 1, b, 2);
4125   PetscCheckSameComm(mat, 1, y, 3);
4126   PetscCheckSameComm(mat, 1, x, 4);
4127   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4128   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);
4129   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);
4130   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);
4131   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);
4132   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4133   MatCheckPreallocated(mat, 1);
4134 
4135   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4136   PetscCall(VecFlag(x, mat->factorerrortype));
4137   if (mat->factorerrortype) {
4138     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4139   } else if (f) {
4140     PetscCall((*f)(mat, b, y, x));
4141   } else {
4142     /* do the solve then the add manually */
4143     if (x != y) {
4144       PetscCall(MatSolveTranspose(mat, b, x));
4145       PetscCall(VecAXPY(x, one, y));
4146     } else {
4147       PetscCall(VecDuplicate(x, &tmp));
4148       PetscCall(VecCopy(x, tmp));
4149       PetscCall(MatSolveTranspose(mat, b, x));
4150       PetscCall(VecAXPY(x, one, tmp));
4151       PetscCall(VecDestroy(&tmp));
4152     }
4153   }
4154   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4155   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4156   PetscFunctionReturn(PETSC_SUCCESS);
4157 }
4158 
4159 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4160 /*@
4161   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4162 
4163   Neighbor-wise Collective
4164 
4165   Input Parameters:
4166 + mat   - the matrix
4167 . b     - the right-hand side
4168 . omega - the relaxation factor
4169 . flag  - flag indicating the type of SOR (see below)
4170 . shift - diagonal shift
4171 . its   - the number of iterations
4172 - lits  - the number of local iterations
4173 
4174   Output Parameter:
4175 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4176 
4177   SOR Flags:
4178 +     `SOR_FORWARD_SWEEP` - forward SOR
4179 .     `SOR_BACKWARD_SWEEP` - backward SOR
4180 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4181 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4182 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4183 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4184 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4185 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4186   upper/lower triangular part of matrix to
4187   vector (with omega)
4188 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4189 
4190   Level: developer
4191 
4192   Notes:
4193   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4194   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4195   on each processor.
4196 
4197   Application programmers will not generally use `MatSOR()` directly,
4198   but instead will employ the `KSP`/`PC` interface.
4199 
4200   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4201 
4202   Most users should employ the `KSP` interface for linear solvers
4203   instead of working directly with matrix algebra routines such as this.
4204   See, e.g., `KSPCreate()`.
4205 
4206   Vectors `x` and `b` CANNOT be the same
4207 
4208   The flags are implemented as bitwise inclusive or operations.
4209   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4210   to specify a zero initial guess for SSOR.
4211 
4212   Developer Note:
4213   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4214 
4215 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4216 @*/
4217 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4218 {
4219   PetscFunctionBegin;
4220   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4221   PetscValidType(mat, 1);
4222   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4223   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4224   PetscCheckSameComm(mat, 1, b, 2);
4225   PetscCheckSameComm(mat, 1, x, 8);
4226   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4227   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4228   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);
4229   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);
4230   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);
4231   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4232   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4233   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4234 
4235   MatCheckPreallocated(mat, 1);
4236   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4237   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4238   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4239   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4240   PetscFunctionReturn(PETSC_SUCCESS);
4241 }
4242 
4243 /*
4244       Default matrix copy routine.
4245 */
4246 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4247 {
4248   PetscInt           i, rstart = 0, rend = 0, nz;
4249   const PetscInt    *cwork;
4250   const PetscScalar *vwork;
4251 
4252   PetscFunctionBegin;
4253   if (B->assembled) PetscCall(MatZeroEntries(B));
4254   if (str == SAME_NONZERO_PATTERN) {
4255     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4256     for (i = rstart; i < rend; i++) {
4257       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4258       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4259       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4260     }
4261   } else {
4262     PetscCall(MatAYPX(B, 0.0, A, str));
4263   }
4264   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4265   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4266   PetscFunctionReturn(PETSC_SUCCESS);
4267 }
4268 
4269 /*@
4270   MatCopy - Copies a matrix to another matrix.
4271 
4272   Collective
4273 
4274   Input Parameters:
4275 + A   - the matrix
4276 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4277 
4278   Output Parameter:
4279 . B - where the copy is put
4280 
4281   Level: intermediate
4282 
4283   Notes:
4284   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4285 
4286   `MatCopy()` copies the matrix entries of a matrix to another existing
4287   matrix (after first zeroing the second matrix).  A related routine is
4288   `MatConvert()`, which first creates a new matrix and then copies the data.
4289 
4290 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4291 @*/
4292 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4293 {
4294   PetscInt i;
4295 
4296   PetscFunctionBegin;
4297   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4298   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4299   PetscValidType(A, 1);
4300   PetscValidType(B, 2);
4301   PetscCheckSameComm(A, 1, B, 2);
4302   MatCheckPreallocated(B, 2);
4303   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4304   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4305   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,
4306              A->cmap->N, B->cmap->N);
4307   MatCheckPreallocated(A, 1);
4308   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4309 
4310   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4311   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4312   else PetscCall(MatCopy_Basic(A, B, str));
4313 
4314   B->stencil.dim = A->stencil.dim;
4315   B->stencil.noc = A->stencil.noc;
4316   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4317     B->stencil.dims[i]   = A->stencil.dims[i];
4318     B->stencil.starts[i] = A->stencil.starts[i];
4319   }
4320 
4321   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4322   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4323   PetscFunctionReturn(PETSC_SUCCESS);
4324 }
4325 
4326 /*@
4327   MatConvert - Converts a matrix to another matrix, either of the same
4328   or different type.
4329 
4330   Collective
4331 
4332   Input Parameters:
4333 + mat     - the matrix
4334 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4335             same type as the original matrix.
4336 - reuse   - denotes if the destination matrix is to be created or reused.
4337             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
4338             `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).
4339 
4340   Output Parameter:
4341 . M - pointer to place new matrix
4342 
4343   Level: intermediate
4344 
4345   Notes:
4346   `MatConvert()` first creates a new matrix and then copies the data from
4347   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4348   entries of one matrix to another already existing matrix context.
4349 
4350   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4351   the MPI communicator of the generated matrix is always the same as the communicator
4352   of the input matrix.
4353 
4354 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4355 @*/
4356 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4357 {
4358   PetscBool  sametype, issame, flg;
4359   PetscBool3 issymmetric, ishermitian;
4360   char       convname[256], mtype[256];
4361   Mat        B;
4362 
4363   PetscFunctionBegin;
4364   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4365   PetscValidType(mat, 1);
4366   PetscAssertPointer(M, 4);
4367   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4368   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4369   MatCheckPreallocated(mat, 1);
4370 
4371   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4372   if (flg) newtype = mtype;
4373 
4374   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4375   PetscCall(PetscStrcmp(newtype, "same", &issame));
4376   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4377   if (reuse == MAT_REUSE_MATRIX) {
4378     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4379     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4380   }
4381 
4382   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4383     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4384     PetscFunctionReturn(PETSC_SUCCESS);
4385   }
4386 
4387   /* Cache Mat options because some converters use MatHeaderReplace  */
4388   issymmetric = mat->symmetric;
4389   ishermitian = mat->hermitian;
4390 
4391   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4392     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4393     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4394   } else {
4395     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4396     const char *prefix[3]                                 = {"seq", "mpi", ""};
4397     PetscInt    i;
4398     /*
4399        Order of precedence:
4400        0) See if newtype is a superclass of the current matrix.
4401        1) See if a specialized converter is known to the current matrix.
4402        2) See if a specialized converter is known to the desired matrix class.
4403        3) See if a good general converter is registered for the desired class
4404           (as of 6/27/03 only MATMPIADJ falls into this category).
4405        4) See if a good general converter is known for the current matrix.
4406        5) Use a really basic converter.
4407     */
4408 
4409     /* 0) See if newtype is a superclass of the current matrix.
4410           i.e mat is mpiaij and newtype is aij */
4411     for (i = 0; i < 2; i++) {
4412       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4413       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4414       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4415       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4416       if (flg) {
4417         if (reuse == MAT_INPLACE_MATRIX) {
4418           PetscCall(PetscInfo(mat, "Early return\n"));
4419           PetscFunctionReturn(PETSC_SUCCESS);
4420         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4421           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4422           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4423           PetscFunctionReturn(PETSC_SUCCESS);
4424         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4425           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4426           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4427           PetscFunctionReturn(PETSC_SUCCESS);
4428         }
4429       }
4430     }
4431     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4432     for (i = 0; i < 3; i++) {
4433       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4434       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4435       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4436       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4437       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4438       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4439       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4440       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4441       if (conv) goto foundconv;
4442     }
4443 
4444     /* 2)  See if a specialized converter is known to the desired matrix class. */
4445     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4446     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4447     PetscCall(MatSetType(B, newtype));
4448     for (i = 0; i < 3; i++) {
4449       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4450       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4451       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4452       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4453       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4454       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4455       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4456       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4457       if (conv) {
4458         PetscCall(MatDestroy(&B));
4459         goto foundconv;
4460       }
4461     }
4462 
4463     /* 3) See if a good general converter is registered for the desired class */
4464     conv = B->ops->convertfrom;
4465     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4466     PetscCall(MatDestroy(&B));
4467     if (conv) goto foundconv;
4468 
4469     /* 4) See if a good general converter is known for the current matrix */
4470     if (mat->ops->convert) conv = mat->ops->convert;
4471     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4472     if (conv) goto foundconv;
4473 
4474     /* 5) Use a really basic converter. */
4475     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4476     conv = MatConvert_Basic;
4477 
4478   foundconv:
4479     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4480     PetscCall((*conv)(mat, newtype, reuse, M));
4481     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4482       /* the block sizes must be same if the mappings are copied over */
4483       (*M)->rmap->bs = mat->rmap->bs;
4484       (*M)->cmap->bs = mat->cmap->bs;
4485       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4486       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4487       (*M)->rmap->mapping = mat->rmap->mapping;
4488       (*M)->cmap->mapping = mat->cmap->mapping;
4489     }
4490     (*M)->stencil.dim = mat->stencil.dim;
4491     (*M)->stencil.noc = mat->stencil.noc;
4492     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4493       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4494       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4495     }
4496     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4497   }
4498   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4499 
4500   /* Copy Mat options */
4501   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4502   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4503   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4504   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4505   PetscFunctionReturn(PETSC_SUCCESS);
4506 }
4507 
4508 /*@
4509   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4510 
4511   Not Collective
4512 
4513   Input Parameter:
4514 . mat - the matrix, must be a factored matrix
4515 
4516   Output Parameter:
4517 . type - the string name of the package (do not free this string)
4518 
4519   Level: intermediate
4520 
4521   Fortran Note:
4522   Pass in an empty string that is long enough and the package name will be copied into it.
4523 
4524 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4525 @*/
4526 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4527 {
4528   PetscErrorCode (*conv)(Mat, MatSolverType *);
4529 
4530   PetscFunctionBegin;
4531   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4532   PetscValidType(mat, 1);
4533   PetscAssertPointer(type, 2);
4534   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4535   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4536   if (conv) PetscCall((*conv)(mat, type));
4537   else *type = MATSOLVERPETSC;
4538   PetscFunctionReturn(PETSC_SUCCESS);
4539 }
4540 
4541 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4542 struct _MatSolverTypeForSpecifcType {
4543   MatType mtype;
4544   /* no entry for MAT_FACTOR_NONE */
4545   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4546   MatSolverTypeForSpecifcType next;
4547 };
4548 
4549 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4550 struct _MatSolverTypeHolder {
4551   char                       *name;
4552   MatSolverTypeForSpecifcType handlers;
4553   MatSolverTypeHolder         next;
4554 };
4555 
4556 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4557 
4558 /*@C
4559   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4560 
4561   Logically Collective, No Fortran Support
4562 
4563   Input Parameters:
4564 + package      - name of the package, for example petsc or superlu
4565 . mtype        - the matrix type that works with this package
4566 . ftype        - the type of factorization supported by the package
4567 - createfactor - routine that will create the factored matrix ready to be used
4568 
4569   Level: developer
4570 
4571 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4572   `MatGetFactor()`
4573 @*/
4574 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4575 {
4576   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4577   PetscBool                   flg;
4578   MatSolverTypeForSpecifcType inext, iprev = NULL;
4579 
4580   PetscFunctionBegin;
4581   PetscCall(MatInitializePackage());
4582   if (!next) {
4583     PetscCall(PetscNew(&MatSolverTypeHolders));
4584     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4585     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4586     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4587     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4588     PetscFunctionReturn(PETSC_SUCCESS);
4589   }
4590   while (next) {
4591     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4592     if (flg) {
4593       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4594       inext = next->handlers;
4595       while (inext) {
4596         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4597         if (flg) {
4598           inext->createfactor[(int)ftype - 1] = createfactor;
4599           PetscFunctionReturn(PETSC_SUCCESS);
4600         }
4601         iprev = inext;
4602         inext = inext->next;
4603       }
4604       PetscCall(PetscNew(&iprev->next));
4605       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4606       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4607       PetscFunctionReturn(PETSC_SUCCESS);
4608     }
4609     prev = next;
4610     next = next->next;
4611   }
4612   PetscCall(PetscNew(&prev->next));
4613   PetscCall(PetscStrallocpy(package, &prev->next->name));
4614   PetscCall(PetscNew(&prev->next->handlers));
4615   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4616   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4617   PetscFunctionReturn(PETSC_SUCCESS);
4618 }
4619 
4620 /*@C
4621   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4622 
4623   Input Parameters:
4624 + 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
4625 . ftype - the type of factorization supported by the type
4626 - mtype - the matrix type that works with this type
4627 
4628   Output Parameters:
4629 + foundtype    - `PETSC_TRUE` if the type was registered
4630 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4631 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4632 
4633   Calling sequence of `createfactor`:
4634 + A     - the matrix providing the factor matrix
4635 . ftype - the `MatFactorType` of the factor requested
4636 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4637 
4638   Level: developer
4639 
4640   Note:
4641   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4642   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4643   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4644 
4645 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4646           `MatInitializePackage()`
4647 @*/
4648 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4649 {
4650   MatSolverTypeHolder         next = MatSolverTypeHolders;
4651   PetscBool                   flg;
4652   MatSolverTypeForSpecifcType inext;
4653 
4654   PetscFunctionBegin;
4655   if (foundtype) *foundtype = PETSC_FALSE;
4656   if (foundmtype) *foundmtype = PETSC_FALSE;
4657   if (createfactor) *createfactor = NULL;
4658 
4659   if (type) {
4660     while (next) {
4661       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4662       if (flg) {
4663         if (foundtype) *foundtype = PETSC_TRUE;
4664         inext = next->handlers;
4665         while (inext) {
4666           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4667           if (flg) {
4668             if (foundmtype) *foundmtype = PETSC_TRUE;
4669             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4670             PetscFunctionReturn(PETSC_SUCCESS);
4671           }
4672           inext = inext->next;
4673         }
4674       }
4675       next = next->next;
4676     }
4677   } else {
4678     while (next) {
4679       inext = next->handlers;
4680       while (inext) {
4681         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4682         if (flg && inext->createfactor[(int)ftype - 1]) {
4683           if (foundtype) *foundtype = PETSC_TRUE;
4684           if (foundmtype) *foundmtype = PETSC_TRUE;
4685           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4686           PetscFunctionReturn(PETSC_SUCCESS);
4687         }
4688         inext = inext->next;
4689       }
4690       next = next->next;
4691     }
4692     /* try with base classes inext->mtype */
4693     next = MatSolverTypeHolders;
4694     while (next) {
4695       inext = next->handlers;
4696       while (inext) {
4697         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4698         if (flg && inext->createfactor[(int)ftype - 1]) {
4699           if (foundtype) *foundtype = PETSC_TRUE;
4700           if (foundmtype) *foundmtype = PETSC_TRUE;
4701           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4702           PetscFunctionReturn(PETSC_SUCCESS);
4703         }
4704         inext = inext->next;
4705       }
4706       next = next->next;
4707     }
4708   }
4709   PetscFunctionReturn(PETSC_SUCCESS);
4710 }
4711 
4712 PetscErrorCode MatSolverTypeDestroy(void)
4713 {
4714   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4715   MatSolverTypeForSpecifcType inext, iprev;
4716 
4717   PetscFunctionBegin;
4718   while (next) {
4719     PetscCall(PetscFree(next->name));
4720     inext = next->handlers;
4721     while (inext) {
4722       PetscCall(PetscFree(inext->mtype));
4723       iprev = inext;
4724       inext = inext->next;
4725       PetscCall(PetscFree(iprev));
4726     }
4727     prev = next;
4728     next = next->next;
4729     PetscCall(PetscFree(prev));
4730   }
4731   MatSolverTypeHolders = NULL;
4732   PetscFunctionReturn(PETSC_SUCCESS);
4733 }
4734 
4735 /*@
4736   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4737 
4738   Logically Collective
4739 
4740   Input Parameter:
4741 . mat - the matrix
4742 
4743   Output Parameter:
4744 . flg - `PETSC_TRUE` if uses the ordering
4745 
4746   Level: developer
4747 
4748   Note:
4749   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4750   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4751 
4752 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4753 @*/
4754 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4755 {
4756   PetscFunctionBegin;
4757   *flg = mat->canuseordering;
4758   PetscFunctionReturn(PETSC_SUCCESS);
4759 }
4760 
4761 /*@
4762   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4763 
4764   Logically Collective
4765 
4766   Input Parameters:
4767 + mat   - the matrix obtained with `MatGetFactor()`
4768 - ftype - the factorization type to be used
4769 
4770   Output Parameter:
4771 . otype - the preferred ordering type
4772 
4773   Level: developer
4774 
4775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4776 @*/
4777 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4778 {
4779   PetscFunctionBegin;
4780   *otype = mat->preferredordering[ftype];
4781   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4782   PetscFunctionReturn(PETSC_SUCCESS);
4783 }
4784 
4785 /*@
4786   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4787 
4788   Collective
4789 
4790   Input Parameters:
4791 + mat   - the matrix
4792 . 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
4793           the other criteria is returned
4794 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4795 
4796   Output Parameter:
4797 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4798 
4799   Options Database Keys:
4800 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4801 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4802                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4803 
4804   Level: intermediate
4805 
4806   Notes:
4807   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4808   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4809 
4810   Users usually access the factorization solvers via `KSP`
4811 
4812   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4813   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
4814 
4815   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4816   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4817   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4818 
4819   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4820   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4821   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4822 
4823   Developer Note:
4824   This should actually be called `MatCreateFactor()` since it creates a new factor object
4825 
4826 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4827           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4828           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4829 @*/
4830 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4831 {
4832   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4833   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4834 
4835   PetscFunctionBegin;
4836   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4837   PetscValidType(mat, 1);
4838 
4839   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4840   MatCheckPreallocated(mat, 1);
4841 
4842   PetscCall(MatIsShell(mat, &shell));
4843   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4844   if (hasop) {
4845     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4846     PetscFunctionReturn(PETSC_SUCCESS);
4847   }
4848 
4849   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4850   if (!foundtype) {
4851     if (type) {
4852       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],
4853               ((PetscObject)mat)->type_name, type);
4854     } else {
4855       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);
4856     }
4857   }
4858   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4859   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);
4860 
4861   PetscCall((*conv)(mat, ftype, f));
4862   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4863   PetscFunctionReturn(PETSC_SUCCESS);
4864 }
4865 
4866 /*@
4867   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4868 
4869   Not Collective
4870 
4871   Input Parameters:
4872 + mat   - the matrix
4873 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4874 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4875 
4876   Output Parameter:
4877 . flg - PETSC_TRUE if the factorization is available
4878 
4879   Level: intermediate
4880 
4881   Notes:
4882   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4883   such as pastix, superlu, mumps etc.
4884 
4885   PETSc must have been ./configure to use the external solver, using the option --download-package
4886 
4887   Developer Note:
4888   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4889 
4890 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4891           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4892 @*/
4893 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4894 {
4895   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4896 
4897   PetscFunctionBegin;
4898   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4899   PetscAssertPointer(flg, 4);
4900 
4901   *flg = PETSC_FALSE;
4902   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4903 
4904   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4905   MatCheckPreallocated(mat, 1);
4906 
4907   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4908   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4909   PetscFunctionReturn(PETSC_SUCCESS);
4910 }
4911 
4912 /*@
4913   MatDuplicate - Duplicates a matrix including the non-zero structure.
4914 
4915   Collective
4916 
4917   Input Parameters:
4918 + mat - the matrix
4919 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4920         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4921 
4922   Output Parameter:
4923 . M - pointer to place new matrix
4924 
4925   Level: intermediate
4926 
4927   Notes:
4928   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4929 
4930   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4931 
4932   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.
4933 
4934   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4935   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4936   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4937 
4938 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4939 @*/
4940 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4941 {
4942   Mat         B;
4943   VecType     vtype;
4944   PetscInt    i;
4945   PetscObject dm, container_h, container_d;
4946   void (*viewf)(void);
4947 
4948   PetscFunctionBegin;
4949   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4950   PetscValidType(mat, 1);
4951   PetscAssertPointer(M, 3);
4952   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4953   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4954   MatCheckPreallocated(mat, 1);
4955 
4956   *M = NULL;
4957   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4958   PetscUseTypeMethod(mat, duplicate, op, M);
4959   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4960   B = *M;
4961 
4962   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4963   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4964   PetscCall(MatGetVecType(mat, &vtype));
4965   PetscCall(MatSetVecType(B, vtype));
4966 
4967   B->stencil.dim = mat->stencil.dim;
4968   B->stencil.noc = mat->stencil.noc;
4969   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4970     B->stencil.dims[i]   = mat->stencil.dims[i];
4971     B->stencil.starts[i] = mat->stencil.starts[i];
4972   }
4973 
4974   B->nooffproczerorows = mat->nooffproczerorows;
4975   B->nooffprocentries  = mat->nooffprocentries;
4976 
4977   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4978   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4979   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4980   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4981   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4982   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4983   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
4984   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4985   PetscFunctionReturn(PETSC_SUCCESS);
4986 }
4987 
4988 /*@
4989   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4990 
4991   Logically Collective
4992 
4993   Input Parameter:
4994 . mat - the matrix
4995 
4996   Output Parameter:
4997 . v - the diagonal of the matrix
4998 
4999   Level: intermediate
5000 
5001   Note:
5002   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5003   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5004   is larger than `ndiag`, the values of the remaining entries are unspecified.
5005 
5006   Currently only correct in parallel for square matrices.
5007 
5008 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5009 @*/
5010 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5011 {
5012   PetscFunctionBegin;
5013   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5014   PetscValidType(mat, 1);
5015   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5016   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5017   MatCheckPreallocated(mat, 1);
5018   if (PetscDefined(USE_DEBUG)) {
5019     PetscInt nv, row, col, ndiag;
5020 
5021     PetscCall(VecGetLocalSize(v, &nv));
5022     PetscCall(MatGetLocalSize(mat, &row, &col));
5023     ndiag = PetscMin(row, col);
5024     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);
5025   }
5026 
5027   PetscUseTypeMethod(mat, getdiagonal, v);
5028   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5029   PetscFunctionReturn(PETSC_SUCCESS);
5030 }
5031 
5032 /*@
5033   MatGetRowMin - Gets the minimum value (of the real part) of each
5034   row of the matrix
5035 
5036   Logically Collective
5037 
5038   Input Parameter:
5039 . mat - the matrix
5040 
5041   Output Parameters:
5042 + v   - the vector for storing the maximums
5043 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5044 
5045   Level: intermediate
5046 
5047   Note:
5048   The result of this call are the same as if one converted the matrix to dense format
5049   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5050 
5051   This code is only implemented for a couple of matrix formats.
5052 
5053 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5054           `MatGetRowMax()`
5055 @*/
5056 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5057 {
5058   PetscFunctionBegin;
5059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5060   PetscValidType(mat, 1);
5061   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5062   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5063 
5064   if (!mat->cmap->N) {
5065     PetscCall(VecSet(v, PETSC_MAX_REAL));
5066     if (idx) {
5067       PetscInt i, m = mat->rmap->n;
5068       for (i = 0; i < m; i++) idx[i] = -1;
5069     }
5070   } else {
5071     MatCheckPreallocated(mat, 1);
5072   }
5073   PetscUseTypeMethod(mat, getrowmin, v, idx);
5074   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5075   PetscFunctionReturn(PETSC_SUCCESS);
5076 }
5077 
5078 /*@
5079   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5080   row of the matrix
5081 
5082   Logically Collective
5083 
5084   Input Parameter:
5085 . mat - the matrix
5086 
5087   Output Parameters:
5088 + v   - the vector for storing the minimums
5089 - idx - the indices of the column found for each row (or `NULL` if not needed)
5090 
5091   Level: intermediate
5092 
5093   Notes:
5094   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5095   row is 0 (the first column).
5096 
5097   This code is only implemented for a couple of matrix formats.
5098 
5099 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5100 @*/
5101 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5102 {
5103   PetscFunctionBegin;
5104   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5105   PetscValidType(mat, 1);
5106   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5107   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5108   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5109 
5110   if (!mat->cmap->N) {
5111     PetscCall(VecSet(v, 0.0));
5112     if (idx) {
5113       PetscInt i, m = mat->rmap->n;
5114       for (i = 0; i < m; i++) idx[i] = -1;
5115     }
5116   } else {
5117     MatCheckPreallocated(mat, 1);
5118     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5119     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5120   }
5121   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5122   PetscFunctionReturn(PETSC_SUCCESS);
5123 }
5124 
5125 /*@
5126   MatGetRowMax - Gets the maximum value (of the real part) of each
5127   row of the matrix
5128 
5129   Logically Collective
5130 
5131   Input Parameter:
5132 . mat - the matrix
5133 
5134   Output Parameters:
5135 + v   - the vector for storing the maximums
5136 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5137 
5138   Level: intermediate
5139 
5140   Notes:
5141   The result of this call are the same as if one converted the matrix to dense format
5142   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5143 
5144   This code is only implemented for a couple of matrix formats.
5145 
5146 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5147 @*/
5148 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5149 {
5150   PetscFunctionBegin;
5151   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5152   PetscValidType(mat, 1);
5153   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5154   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5155 
5156   if (!mat->cmap->N) {
5157     PetscCall(VecSet(v, PETSC_MIN_REAL));
5158     if (idx) {
5159       PetscInt i, m = mat->rmap->n;
5160       for (i = 0; i < m; i++) idx[i] = -1;
5161     }
5162   } else {
5163     MatCheckPreallocated(mat, 1);
5164     PetscUseTypeMethod(mat, getrowmax, v, idx);
5165   }
5166   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5167   PetscFunctionReturn(PETSC_SUCCESS);
5168 }
5169 
5170 /*@
5171   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5172   row of the matrix
5173 
5174   Logically Collective
5175 
5176   Input Parameter:
5177 . mat - the matrix
5178 
5179   Output Parameters:
5180 + v   - the vector for storing the maximums
5181 - idx - the indices of the column found for each row (or `NULL` if not needed)
5182 
5183   Level: intermediate
5184 
5185   Notes:
5186   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5187   row is 0 (the first column).
5188 
5189   This code is only implemented for a couple of matrix formats.
5190 
5191 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5192 @*/
5193 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5194 {
5195   PetscFunctionBegin;
5196   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5197   PetscValidType(mat, 1);
5198   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5199   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5200 
5201   if (!mat->cmap->N) {
5202     PetscCall(VecSet(v, 0.0));
5203     if (idx) {
5204       PetscInt i, m = mat->rmap->n;
5205       for (i = 0; i < m; i++) idx[i] = -1;
5206     }
5207   } else {
5208     MatCheckPreallocated(mat, 1);
5209     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5210     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5211   }
5212   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5213   PetscFunctionReturn(PETSC_SUCCESS);
5214 }
5215 
5216 /*@
5217   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5218 
5219   Logically Collective
5220 
5221   Input Parameter:
5222 . mat - the matrix
5223 
5224   Output Parameter:
5225 . v - the vector for storing the sum
5226 
5227   Level: intermediate
5228 
5229   This code is only implemented for a couple of matrix formats.
5230 
5231 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5232 @*/
5233 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5234 {
5235   PetscFunctionBegin;
5236   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5237   PetscValidType(mat, 1);
5238   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5239   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5240 
5241   if (!mat->cmap->N) {
5242     PetscCall(VecSet(v, 0.0));
5243   } else {
5244     MatCheckPreallocated(mat, 1);
5245     PetscUseTypeMethod(mat, getrowsumabs, v);
5246   }
5247   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5248   PetscFunctionReturn(PETSC_SUCCESS);
5249 }
5250 
5251 /*@
5252   MatGetRowSum - Gets the sum of each row of the matrix
5253 
5254   Logically or Neighborhood Collective
5255 
5256   Input Parameter:
5257 . mat - the matrix
5258 
5259   Output Parameter:
5260 . v - the vector for storing the sum of rows
5261 
5262   Level: intermediate
5263 
5264   Note:
5265   This code is slow since it is not currently specialized for different formats
5266 
5267 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5268 @*/
5269 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5270 {
5271   Vec ones;
5272 
5273   PetscFunctionBegin;
5274   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5275   PetscValidType(mat, 1);
5276   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5277   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5278   MatCheckPreallocated(mat, 1);
5279   PetscCall(MatCreateVecs(mat, &ones, NULL));
5280   PetscCall(VecSet(ones, 1.));
5281   PetscCall(MatMult(mat, ones, v));
5282   PetscCall(VecDestroy(&ones));
5283   PetscFunctionReturn(PETSC_SUCCESS);
5284 }
5285 
5286 /*@
5287   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5288   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5289 
5290   Collective
5291 
5292   Input Parameter:
5293 . mat - the matrix to provide the transpose
5294 
5295   Output Parameter:
5296 . 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
5297 
5298   Level: advanced
5299 
5300   Note:
5301   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
5302   routine allows bypassing that call.
5303 
5304 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5305 @*/
5306 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5307 {
5308   MatParentState *rb = NULL;
5309 
5310   PetscFunctionBegin;
5311   PetscCall(PetscNew(&rb));
5312   rb->id    = ((PetscObject)mat)->id;
5313   rb->state = 0;
5314   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5315   PetscCall(PetscObjectContainerCompose((PetscObject)B, "MatTransposeParent", rb, PetscContainerUserDestroyDefault));
5316   PetscFunctionReturn(PETSC_SUCCESS);
5317 }
5318 
5319 /*@
5320   MatTranspose - Computes the transpose of a matrix, either in-place or out-of-place.
5321 
5322   Collective
5323 
5324   Input Parameters:
5325 + mat   - the matrix to transpose
5326 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5327 
5328   Output Parameter:
5329 . B - the transpose of the matrix
5330 
5331   Level: intermediate
5332 
5333   Notes:
5334   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5335 
5336   `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
5337   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5338 
5339   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.
5340 
5341   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose but don't need the storage to be changed.
5342   For example, the result of `MatCreateTranspose()` will compute the transpose of the given matrix times a vector for matrix-vector products computed with `MatMult()`.
5343 
5344   If `mat` is unchanged from the last call this function returns immediately without recomputing the result
5345 
5346   If you only need the symbolic transpose of a matrix, and not the numerical values, use `MatTransposeSymbolic()`
5347 
5348 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5349           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5350 @*/
5351 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5352 {
5353   PetscContainer  rB = NULL;
5354   MatParentState *rb = NULL;
5355 
5356   PetscFunctionBegin;
5357   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5358   PetscValidType(mat, 1);
5359   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5360   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5361   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5362   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5363   MatCheckPreallocated(mat, 1);
5364   if (reuse == MAT_REUSE_MATRIX) {
5365     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5366     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5367     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5368     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5369     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5370   }
5371 
5372   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5373   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5374     PetscUseTypeMethod(mat, transpose, reuse, B);
5375     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5376   }
5377   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5378 
5379   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5380   if (reuse != MAT_INPLACE_MATRIX) {
5381     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5382     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5383     rb->state        = ((PetscObject)mat)->state;
5384     rb->nonzerostate = mat->nonzerostate;
5385   }
5386   PetscFunctionReturn(PETSC_SUCCESS);
5387 }
5388 
5389 /*@
5390   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5391 
5392   Collective
5393 
5394   Input Parameter:
5395 . A - the matrix to transpose
5396 
5397   Output Parameter:
5398 . 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
5399       numerical portion.
5400 
5401   Level: intermediate
5402 
5403   Note:
5404   This is not supported for many matrix types, use `MatTranspose()` in those cases
5405 
5406 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5407 @*/
5408 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5409 {
5410   PetscFunctionBegin;
5411   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5412   PetscValidType(A, 1);
5413   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5414   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5415   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5416   PetscUseTypeMethod(A, transposesymbolic, B);
5417   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5418 
5419   PetscCall(MatTransposeSetPrecursor(A, *B));
5420   PetscFunctionReturn(PETSC_SUCCESS);
5421 }
5422 
5423 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5424 {
5425   PetscContainer  rB;
5426   MatParentState *rb;
5427 
5428   PetscFunctionBegin;
5429   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5430   PetscValidType(A, 1);
5431   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5432   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5433   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5434   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5435   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5436   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5437   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5438   PetscFunctionReturn(PETSC_SUCCESS);
5439 }
5440 
5441 /*@
5442   MatIsTranspose - Test whether a matrix is another one's transpose,
5443   or its own, in which case it tests symmetry.
5444 
5445   Collective
5446 
5447   Input Parameters:
5448 + A   - the matrix to test
5449 . B   - the matrix to test against, this can equal the first parameter
5450 - tol - tolerance, differences between entries smaller than this are counted as zero
5451 
5452   Output Parameter:
5453 . flg - the result
5454 
5455   Level: intermediate
5456 
5457   Notes:
5458   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5459   test involves parallel copies of the block off-diagonal parts of the matrix.
5460 
5461 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5462 @*/
5463 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5464 {
5465   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5466 
5467   PetscFunctionBegin;
5468   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5469   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5470   PetscAssertPointer(flg, 4);
5471   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5472   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5473   *flg = PETSC_FALSE;
5474   if (f && g) {
5475     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5476     PetscCall((*f)(A, B, tol, flg));
5477   } else {
5478     MatType mattype;
5479 
5480     PetscCall(MatGetType(f ? B : A, &mattype));
5481     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5482   }
5483   PetscFunctionReturn(PETSC_SUCCESS);
5484 }
5485 
5486 /*@
5487   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5488 
5489   Collective
5490 
5491   Input Parameters:
5492 + mat   - the matrix to transpose and complex conjugate
5493 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5494 
5495   Output Parameter:
5496 . B - the Hermitian transpose
5497 
5498   Level: intermediate
5499 
5500 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5501 @*/
5502 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5503 {
5504   PetscFunctionBegin;
5505   PetscCall(MatTranspose(mat, reuse, B));
5506 #if defined(PETSC_USE_COMPLEX)
5507   PetscCall(MatConjugate(*B));
5508 #endif
5509   PetscFunctionReturn(PETSC_SUCCESS);
5510 }
5511 
5512 /*@
5513   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5514 
5515   Collective
5516 
5517   Input Parameters:
5518 + A   - the matrix to test
5519 . B   - the matrix to test against, this can equal the first parameter
5520 - tol - tolerance, differences between entries smaller than this are counted as zero
5521 
5522   Output Parameter:
5523 . flg - the result
5524 
5525   Level: intermediate
5526 
5527   Notes:
5528   Only available for `MATAIJ` matrices.
5529 
5530   The sequential algorithm
5531   has a running time of the order of the number of nonzeros; the parallel
5532   test involves parallel copies of the block off-diagonal parts of the matrix.
5533 
5534 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5535 @*/
5536 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5537 {
5538   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5539 
5540   PetscFunctionBegin;
5541   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5542   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5543   PetscAssertPointer(flg, 4);
5544   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5545   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5546   if (f && g) {
5547     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5548     PetscCall((*f)(A, B, tol, flg));
5549   }
5550   PetscFunctionReturn(PETSC_SUCCESS);
5551 }
5552 
5553 /*@
5554   MatPermute - Creates a new matrix with rows and columns permuted from the
5555   original.
5556 
5557   Collective
5558 
5559   Input Parameters:
5560 + mat - the matrix to permute
5561 . row - row permutation, each processor supplies only the permutation for its rows
5562 - col - column permutation, each processor supplies only the permutation for its columns
5563 
5564   Output Parameter:
5565 . B - the permuted matrix
5566 
5567   Level: advanced
5568 
5569   Note:
5570   The index sets map from row/col of permuted matrix to row/col of original matrix.
5571   The index sets should be on the same communicator as mat and have the same local sizes.
5572 
5573   Developer Note:
5574   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5575   exploit the fact that row and col are permutations, consider implementing the
5576   more general `MatCreateSubMatrix()` instead.
5577 
5578 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5579 @*/
5580 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5581 {
5582   PetscFunctionBegin;
5583   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5584   PetscValidType(mat, 1);
5585   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5586   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5587   PetscAssertPointer(B, 4);
5588   PetscCheckSameComm(mat, 1, row, 2);
5589   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5590   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5591   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5592   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5593   MatCheckPreallocated(mat, 1);
5594 
5595   if (mat->ops->permute) {
5596     PetscUseTypeMethod(mat, permute, row, col, B);
5597     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5598   } else {
5599     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5600   }
5601   PetscFunctionReturn(PETSC_SUCCESS);
5602 }
5603 
5604 /*@
5605   MatEqual - Compares two matrices.
5606 
5607   Collective
5608 
5609   Input Parameters:
5610 + A - the first matrix
5611 - B - the second matrix
5612 
5613   Output Parameter:
5614 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5615 
5616   Level: intermediate
5617 
5618 .seealso: [](ch_matrices), `Mat`
5619 @*/
5620 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5621 {
5622   PetscFunctionBegin;
5623   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5624   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5625   PetscValidType(A, 1);
5626   PetscValidType(B, 2);
5627   PetscAssertPointer(flg, 3);
5628   PetscCheckSameComm(A, 1, B, 2);
5629   MatCheckPreallocated(A, 1);
5630   MatCheckPreallocated(B, 2);
5631   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5632   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5633   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,
5634              B->cmap->N);
5635   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5636     PetscUseTypeMethod(A, equal, B, flg);
5637   } else {
5638     PetscCall(MatMultEqual(A, B, 10, flg));
5639   }
5640   PetscFunctionReturn(PETSC_SUCCESS);
5641 }
5642 
5643 /*@
5644   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5645   matrices that are stored as vectors.  Either of the two scaling
5646   matrices can be `NULL`.
5647 
5648   Collective
5649 
5650   Input Parameters:
5651 + mat - the matrix to be scaled
5652 . l   - the left scaling vector (or `NULL`)
5653 - r   - the right scaling vector (or `NULL`)
5654 
5655   Level: intermediate
5656 
5657   Note:
5658   `MatDiagonalScale()` computes $A = LAR$, where
5659   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5660   The L scales the rows of the matrix, the R scales the columns of the matrix.
5661 
5662 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5663 @*/
5664 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5665 {
5666   PetscFunctionBegin;
5667   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5668   PetscValidType(mat, 1);
5669   if (l) {
5670     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5671     PetscCheckSameComm(mat, 1, l, 2);
5672   }
5673   if (r) {
5674     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5675     PetscCheckSameComm(mat, 1, r, 3);
5676   }
5677   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5678   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5679   MatCheckPreallocated(mat, 1);
5680   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5681 
5682   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5683   PetscUseTypeMethod(mat, diagonalscale, l, r);
5684   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5685   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5686   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5687   PetscFunctionReturn(PETSC_SUCCESS);
5688 }
5689 
5690 /*@
5691   MatScale - Scales all elements of a matrix by a given number.
5692 
5693   Logically Collective
5694 
5695   Input Parameters:
5696 + mat - the matrix to be scaled
5697 - a   - the scaling value
5698 
5699   Level: intermediate
5700 
5701 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5702 @*/
5703 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5704 {
5705   PetscFunctionBegin;
5706   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5707   PetscValidType(mat, 1);
5708   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5709   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5710   PetscValidLogicalCollectiveScalar(mat, a, 2);
5711   MatCheckPreallocated(mat, 1);
5712 
5713   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5714   if (a != (PetscScalar)1.0) {
5715     PetscUseTypeMethod(mat, scale, a);
5716     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5717   }
5718   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5719   PetscFunctionReturn(PETSC_SUCCESS);
5720 }
5721 
5722 /*@
5723   MatNorm - Calculates various norms of a matrix.
5724 
5725   Collective
5726 
5727   Input Parameters:
5728 + mat  - the matrix
5729 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5730 
5731   Output Parameter:
5732 . nrm - the resulting norm
5733 
5734   Level: intermediate
5735 
5736 .seealso: [](ch_matrices), `Mat`
5737 @*/
5738 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5739 {
5740   PetscFunctionBegin;
5741   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5742   PetscValidType(mat, 1);
5743   PetscAssertPointer(nrm, 3);
5744 
5745   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5746   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5747   MatCheckPreallocated(mat, 1);
5748 
5749   PetscUseTypeMethod(mat, norm, type, nrm);
5750   PetscFunctionReturn(PETSC_SUCCESS);
5751 }
5752 
5753 /*
5754      This variable is used to prevent counting of MatAssemblyBegin() that
5755    are called from within a MatAssemblyEnd().
5756 */
5757 static PetscInt MatAssemblyEnd_InUse = 0;
5758 /*@
5759   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5760   be called after completing all calls to `MatSetValues()`.
5761 
5762   Collective
5763 
5764   Input Parameters:
5765 + mat  - the matrix
5766 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5767 
5768   Level: beginner
5769 
5770   Notes:
5771   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5772   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5773 
5774   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5775   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5776   using the matrix.
5777 
5778   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5779   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
5780   a global collective operation requiring all processes that share the matrix.
5781 
5782   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5783   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5784   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5785 
5786 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5787 @*/
5788 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5789 {
5790   PetscFunctionBegin;
5791   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5792   PetscValidType(mat, 1);
5793   MatCheckPreallocated(mat, 1);
5794   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5795   if (mat->assembled) {
5796     mat->was_assembled = PETSC_TRUE;
5797     mat->assembled     = PETSC_FALSE;
5798   }
5799 
5800   if (!MatAssemblyEnd_InUse) {
5801     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5802     PetscTryTypeMethod(mat, assemblybegin, type);
5803     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5804   } else PetscTryTypeMethod(mat, assemblybegin, type);
5805   PetscFunctionReturn(PETSC_SUCCESS);
5806 }
5807 
5808 /*@
5809   MatAssembled - Indicates if a matrix has been assembled and is ready for
5810   use; for example, in matrix-vector product.
5811 
5812   Not Collective
5813 
5814   Input Parameter:
5815 . mat - the matrix
5816 
5817   Output Parameter:
5818 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5819 
5820   Level: advanced
5821 
5822 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5823 @*/
5824 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5825 {
5826   PetscFunctionBegin;
5827   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5828   PetscAssertPointer(assembled, 2);
5829   *assembled = mat->assembled;
5830   PetscFunctionReturn(PETSC_SUCCESS);
5831 }
5832 
5833 /*@
5834   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5835   be called after `MatAssemblyBegin()`.
5836 
5837   Collective
5838 
5839   Input Parameters:
5840 + mat  - the matrix
5841 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5842 
5843   Options Database Keys:
5844 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5845 . -mat_view ::ascii_info_detail      - Prints more detailed info
5846 . -mat_view                          - Prints matrix in ASCII format
5847 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5848 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5849 . -display <name>                    - Sets display name (default is host)
5850 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5851 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5852 . -viewer_socket_machine <machine>   - Machine to use for socket
5853 . -viewer_socket_port <port>         - Port number to use for socket
5854 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5855 
5856   Level: beginner
5857 
5858 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5859 @*/
5860 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5861 {
5862   static PetscInt inassm = 0;
5863   PetscBool       flg    = PETSC_FALSE;
5864 
5865   PetscFunctionBegin;
5866   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5867   PetscValidType(mat, 1);
5868 
5869   inassm++;
5870   MatAssemblyEnd_InUse++;
5871   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5872     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5873     PetscTryTypeMethod(mat, assemblyend, type);
5874     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5875   } else PetscTryTypeMethod(mat, assemblyend, type);
5876 
5877   /* Flush assembly is not a true assembly */
5878   if (type != MAT_FLUSH_ASSEMBLY) {
5879     if (mat->num_ass) {
5880       if (!mat->symmetry_eternal) {
5881         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5882         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5883       }
5884       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5885       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5886     }
5887     mat->num_ass++;
5888     mat->assembled        = PETSC_TRUE;
5889     mat->ass_nonzerostate = mat->nonzerostate;
5890   }
5891 
5892   mat->insertmode = NOT_SET_VALUES;
5893   MatAssemblyEnd_InUse--;
5894   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5895   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5896     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5897 
5898     if (mat->checksymmetryonassembly) {
5899       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5900       if (flg) {
5901         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5902       } else {
5903         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5904       }
5905     }
5906     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5907   }
5908   inassm--;
5909   PetscFunctionReturn(PETSC_SUCCESS);
5910 }
5911 
5912 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5913 /*@
5914   MatSetOption - Sets a parameter option for a matrix. Some options
5915   may be specific to certain storage formats.  Some options
5916   determine how values will be inserted (or added). Sorted,
5917   row-oriented input will generally assemble the fastest. The default
5918   is row-oriented.
5919 
5920   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5921 
5922   Input Parameters:
5923 + mat - the matrix
5924 . op  - the option, one of those listed below (and possibly others),
5925 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5926 
5927   Options Describing Matrix Structure:
5928 + `MAT_SPD`                         - symmetric positive definite
5929 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5930 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5931 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5932 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5933 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5934 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5935 
5936    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5937    do not need to be computed (usually at a high cost)
5938 
5939    Options For Use with `MatSetValues()`:
5940    Insert a logically dense subblock, which can be
5941 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5942 
5943    These options reflect the data you pass in with `MatSetValues()`; it has
5944    nothing to do with how the data is stored internally in the matrix
5945    data structure.
5946 
5947    When (re)assembling a matrix, we can restrict the input for
5948    efficiency/debugging purposes.  These options include
5949 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5950 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5951 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5952 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5953 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5954 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5955         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5956         performance for very large process counts.
5957 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5958         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5959         functions, instead sending only neighbor messages.
5960 
5961   Level: intermediate
5962 
5963   Notes:
5964   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5965 
5966   Some options are relevant only for particular matrix types and
5967   are thus ignored by others.  Other options are not supported by
5968   certain matrix types and will generate an error message if set.
5969 
5970   If using Fortran to compute a matrix, one may need to
5971   use the column-oriented option (or convert to the row-oriented
5972   format).
5973 
5974   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5975   that would generate a new entry in the nonzero structure is instead
5976   ignored.  Thus, if memory has not already been allocated for this particular
5977   data, then the insertion is ignored. For dense matrices, in which
5978   the entire array is allocated, no entries are ever ignored.
5979   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5980 
5981   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5982   that would generate a new entry in the nonzero structure instead produces
5983   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
5984 
5985   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5986   that would generate a new entry that has not been preallocated will
5987   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5988   only.) This is a useful flag when debugging matrix memory preallocation.
5989   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5990 
5991   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5992   other processors should be dropped, rather than stashed.
5993   This is useful if you know that the "owning" processor is also
5994   always generating the correct matrix entries, so that PETSc need
5995   not transfer duplicate entries generated on another processor.
5996 
5997   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5998   searches during matrix assembly. When this flag is set, the hash table
5999   is created during the first matrix assembly. This hash table is
6000   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6001   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6002   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6003   supported by `MATMPIBAIJ` format only.
6004 
6005   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6006   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6007 
6008   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6009   a zero location in the matrix
6010 
6011   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6012 
6013   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6014   zero row routines and thus improves performance for very large process counts.
6015 
6016   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6017   part of the matrix (since they should match the upper triangular part).
6018 
6019   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6020   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6021   with finite difference schemes with non-periodic boundary conditions.
6022 
6023   Developer Note:
6024   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6025   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6026   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6027   not changed.
6028 
6029 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6030 @*/
6031 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6032 {
6033   PetscFunctionBegin;
6034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6035   if (op > 0) {
6036     PetscValidLogicalCollectiveEnum(mat, op, 2);
6037     PetscValidLogicalCollectiveBool(mat, flg, 3);
6038   }
6039 
6040   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);
6041 
6042   switch (op) {
6043   case MAT_FORCE_DIAGONAL_ENTRIES:
6044     mat->force_diagonals = flg;
6045     PetscFunctionReturn(PETSC_SUCCESS);
6046   case MAT_NO_OFF_PROC_ENTRIES:
6047     mat->nooffprocentries = flg;
6048     PetscFunctionReturn(PETSC_SUCCESS);
6049   case MAT_SUBSET_OFF_PROC_ENTRIES:
6050     mat->assembly_subset = flg;
6051     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6052 #if !defined(PETSC_HAVE_MPIUNI)
6053       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6054 #endif
6055       mat->stash.first_assembly_done = PETSC_FALSE;
6056     }
6057     PetscFunctionReturn(PETSC_SUCCESS);
6058   case MAT_NO_OFF_PROC_ZERO_ROWS:
6059     mat->nooffproczerorows = flg;
6060     PetscFunctionReturn(PETSC_SUCCESS);
6061   case MAT_SPD:
6062     if (flg) {
6063       mat->spd                    = PETSC_BOOL3_TRUE;
6064       mat->symmetric              = PETSC_BOOL3_TRUE;
6065       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6066     } else {
6067       mat->spd = PETSC_BOOL3_FALSE;
6068     }
6069     break;
6070   case MAT_SYMMETRIC:
6071     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6072     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6073 #if !defined(PETSC_USE_COMPLEX)
6074     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6075 #endif
6076     break;
6077   case MAT_HERMITIAN:
6078     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6079     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6080 #if !defined(PETSC_USE_COMPLEX)
6081     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6082 #endif
6083     break;
6084   case MAT_STRUCTURALLY_SYMMETRIC:
6085     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6086     break;
6087   case MAT_SYMMETRY_ETERNAL:
6088     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");
6089     mat->symmetry_eternal = flg;
6090     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6091     break;
6092   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6093     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");
6094     mat->structural_symmetry_eternal = flg;
6095     break;
6096   case MAT_SPD_ETERNAL:
6097     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");
6098     mat->spd_eternal = flg;
6099     if (flg) {
6100       mat->structural_symmetry_eternal = PETSC_TRUE;
6101       mat->symmetry_eternal            = PETSC_TRUE;
6102     }
6103     break;
6104   case MAT_STRUCTURE_ONLY:
6105     mat->structure_only = flg;
6106     break;
6107   case MAT_SORTED_FULL:
6108     mat->sortedfull = flg;
6109     break;
6110   default:
6111     break;
6112   }
6113   PetscTryTypeMethod(mat, setoption, op, flg);
6114   PetscFunctionReturn(PETSC_SUCCESS);
6115 }
6116 
6117 /*@
6118   MatGetOption - Gets a parameter option that has been set for a matrix.
6119 
6120   Logically Collective
6121 
6122   Input Parameters:
6123 + mat - the matrix
6124 - op  - the option, this only responds to certain options, check the code for which ones
6125 
6126   Output Parameter:
6127 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6128 
6129   Level: intermediate
6130 
6131   Notes:
6132   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6133 
6134   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6135   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6136 
6137 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6138     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6139 @*/
6140 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6141 {
6142   PetscFunctionBegin;
6143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6144   PetscValidType(mat, 1);
6145 
6146   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);
6147   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()");
6148 
6149   switch (op) {
6150   case MAT_NO_OFF_PROC_ENTRIES:
6151     *flg = mat->nooffprocentries;
6152     break;
6153   case MAT_NO_OFF_PROC_ZERO_ROWS:
6154     *flg = mat->nooffproczerorows;
6155     break;
6156   case MAT_SYMMETRIC:
6157     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6158     break;
6159   case MAT_HERMITIAN:
6160     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6161     break;
6162   case MAT_STRUCTURALLY_SYMMETRIC:
6163     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6164     break;
6165   case MAT_SPD:
6166     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6167     break;
6168   case MAT_SYMMETRY_ETERNAL:
6169     *flg = mat->symmetry_eternal;
6170     break;
6171   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6172     *flg = mat->symmetry_eternal;
6173     break;
6174   default:
6175     break;
6176   }
6177   PetscFunctionReturn(PETSC_SUCCESS);
6178 }
6179 
6180 /*@
6181   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6182   this routine retains the old nonzero structure.
6183 
6184   Logically Collective
6185 
6186   Input Parameter:
6187 . mat - the matrix
6188 
6189   Level: intermediate
6190 
6191   Note:
6192   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.
6193   See the Performance chapter of the users manual for information on preallocating matrices.
6194 
6195 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6196 @*/
6197 PetscErrorCode MatZeroEntries(Mat mat)
6198 {
6199   PetscFunctionBegin;
6200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6201   PetscValidType(mat, 1);
6202   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6203   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");
6204   MatCheckPreallocated(mat, 1);
6205 
6206   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6207   PetscUseTypeMethod(mat, zeroentries);
6208   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6209   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6210   PetscFunctionReturn(PETSC_SUCCESS);
6211 }
6212 
6213 /*@
6214   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6215   of a set of rows and columns of a matrix.
6216 
6217   Collective
6218 
6219   Input Parameters:
6220 + mat     - the matrix
6221 . numRows - the number of rows/columns to zero
6222 . rows    - the global row indices
6223 . diag    - value put in the diagonal of the eliminated rows
6224 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6225 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6226 
6227   Level: intermediate
6228 
6229   Notes:
6230   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6231 
6232   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6233   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
6234 
6235   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6236   Krylov method to take advantage of the known solution on the zeroed rows.
6237 
6238   For the parallel case, all processes that share the matrix (i.e.,
6239   those in the communicator used for matrix creation) MUST call this
6240   routine, regardless of whether any rows being zeroed are owned by
6241   them.
6242 
6243   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6244   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
6245   missing.
6246 
6247   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6248   list only rows local to itself).
6249 
6250   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6251 
6252 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6253           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6254 @*/
6255 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6256 {
6257   PetscFunctionBegin;
6258   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6259   PetscValidType(mat, 1);
6260   if (numRows) PetscAssertPointer(rows, 3);
6261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6262   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6263   MatCheckPreallocated(mat, 1);
6264 
6265   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6266   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6267   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6268   PetscFunctionReturn(PETSC_SUCCESS);
6269 }
6270 
6271 /*@
6272   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6273   of a set of rows and columns of a matrix.
6274 
6275   Collective
6276 
6277   Input Parameters:
6278 + mat  - the matrix
6279 . is   - the rows to zero
6280 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6281 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6282 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6283 
6284   Level: intermediate
6285 
6286   Note:
6287   See `MatZeroRowsColumns()` for details on how this routine operates.
6288 
6289 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6290           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6291 @*/
6292 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6293 {
6294   PetscInt        numRows;
6295   const PetscInt *rows;
6296 
6297   PetscFunctionBegin;
6298   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6299   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6300   PetscValidType(mat, 1);
6301   PetscValidType(is, 2);
6302   PetscCall(ISGetLocalSize(is, &numRows));
6303   PetscCall(ISGetIndices(is, &rows));
6304   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6305   PetscCall(ISRestoreIndices(is, &rows));
6306   PetscFunctionReturn(PETSC_SUCCESS);
6307 }
6308 
6309 /*@
6310   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6311   of a set of rows of a matrix.
6312 
6313   Collective
6314 
6315   Input Parameters:
6316 + mat     - the matrix
6317 . numRows - the number of rows to zero
6318 . rows    - the global row indices
6319 . diag    - value put in the diagonal of the zeroed rows
6320 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6321 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6322 
6323   Level: intermediate
6324 
6325   Notes:
6326   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6327 
6328   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6329 
6330   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6331   Krylov method to take advantage of the known solution on the zeroed rows.
6332 
6333   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)
6334   from the matrix.
6335 
6336   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6337   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense
6338   formats this does not alter the nonzero structure.
6339 
6340   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6341   of the matrix is not changed the values are
6342   merely zeroed.
6343 
6344   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6345   formats can optionally remove the main diagonal entry from the
6346   nonzero structure as well, by passing 0.0 as the final argument).
6347 
6348   For the parallel case, all processes that share the matrix (i.e.,
6349   those in the communicator used for matrix creation) MUST call this
6350   routine, regardless of whether any rows being zeroed are owned by
6351   them.
6352 
6353   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6354   list only rows local to itself).
6355 
6356   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6357   owns that are to be zeroed. This saves a global synchronization in the implementation.
6358 
6359 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6360           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6361 @*/
6362 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6363 {
6364   PetscFunctionBegin;
6365   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6366   PetscValidType(mat, 1);
6367   if (numRows) PetscAssertPointer(rows, 3);
6368   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6369   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6370   MatCheckPreallocated(mat, 1);
6371 
6372   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6373   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6374   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6375   PetscFunctionReturn(PETSC_SUCCESS);
6376 }
6377 
6378 /*@
6379   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6380   of a set of rows of a matrix indicated by an `IS`
6381 
6382   Collective
6383 
6384   Input Parameters:
6385 + mat  - the matrix
6386 . is   - index set, `IS`, of rows to remove (if `NULL` then no row is removed)
6387 . diag - value put in all diagonals of eliminated rows
6388 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6389 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6390 
6391   Level: intermediate
6392 
6393   Note:
6394   See `MatZeroRows()` for details on how this routine operates.
6395 
6396 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6397           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `IS`
6398 @*/
6399 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6400 {
6401   PetscInt        numRows = 0;
6402   const PetscInt *rows    = NULL;
6403 
6404   PetscFunctionBegin;
6405   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6406   PetscValidType(mat, 1);
6407   if (is) {
6408     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6409     PetscCall(ISGetLocalSize(is, &numRows));
6410     PetscCall(ISGetIndices(is, &rows));
6411   }
6412   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6413   if (is) PetscCall(ISRestoreIndices(is, &rows));
6414   PetscFunctionReturn(PETSC_SUCCESS);
6415 }
6416 
6417 /*@
6418   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6419   of a set of rows of a matrix indicated by a `MatStencil`. These rows must be local to the process.
6420 
6421   Collective
6422 
6423   Input Parameters:
6424 + mat     - the matrix
6425 . numRows - the number of rows to remove
6426 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows indicated by an array of `MatStencil`
6427 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6428 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6429 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6430 
6431   Level: intermediate
6432 
6433   Notes:
6434   See `MatZeroRows()` for details on how this routine operates.
6435 
6436   The grid coordinates are across the entire grid, not just the local portion
6437 
6438   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6439   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6440   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6441   `DM_BOUNDARY_PERIODIC` boundary type.
6442 
6443   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
6444   a single value per point) you can skip filling those indices.
6445 
6446   Fortran Note:
6447   `idxm` and `idxn` should be declared as
6448 $     MatStencil idxm(4, m)
6449   and the values inserted using
6450 .vb
6451     idxm(MatStencil_i, 1) = i
6452     idxm(MatStencil_j, 1) = j
6453     idxm(MatStencil_k, 1) = k
6454     idxm(MatStencil_c, 1) = c
6455    etc
6456 .ve
6457 
6458 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6459           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6460 @*/
6461 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6462 {
6463   PetscInt  dim    = mat->stencil.dim;
6464   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6465   PetscInt *dims   = mat->stencil.dims + 1;
6466   PetscInt *starts = mat->stencil.starts;
6467   PetscInt *dxm    = (PetscInt *)rows;
6468   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6469 
6470   PetscFunctionBegin;
6471   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6472   PetscValidType(mat, 1);
6473   if (numRows) PetscAssertPointer(rows, 3);
6474 
6475   PetscCall(PetscMalloc1(numRows, &jdxm));
6476   for (i = 0; i < numRows; ++i) {
6477     /* Skip unused dimensions (they are ordered k, j, i, c) */
6478     for (j = 0; j < 3 - sdim; ++j) dxm++;
6479     /* Local index in X dir */
6480     tmp = *dxm++ - starts[0];
6481     /* Loop over remaining dimensions */
6482     for (j = 0; j < dim - 1; ++j) {
6483       /* If nonlocal, set index to be negative */
6484       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6485       /* Update local index */
6486       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6487     }
6488     /* Skip component slot if necessary */
6489     if (mat->stencil.noc) dxm++;
6490     /* Local row number */
6491     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6492   }
6493   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6494   PetscCall(PetscFree(jdxm));
6495   PetscFunctionReturn(PETSC_SUCCESS);
6496 }
6497 
6498 /*@
6499   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6500   of a set of rows and columns of a matrix.
6501 
6502   Collective
6503 
6504   Input Parameters:
6505 + mat     - the matrix
6506 . numRows - the number of rows/columns to remove
6507 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6508 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6509 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6510 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6511 
6512   Level: intermediate
6513 
6514   Notes:
6515   See `MatZeroRowsColumns()` for details on how this routine operates.
6516 
6517   The grid coordinates are across the entire grid, not just the local portion
6518 
6519   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6520   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6521   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6522   `DM_BOUNDARY_PERIODIC` boundary type.
6523 
6524   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
6525   a single value per point) you can skip filling those indices.
6526 
6527   Fortran Note:
6528   `idxm` and `idxn` should be declared as
6529 $     MatStencil idxm(4, m)
6530   and the values inserted using
6531 .vb
6532     idxm(MatStencil_i, 1) = i
6533     idxm(MatStencil_j, 1) = j
6534     idxm(MatStencil_k, 1) = k
6535     idxm(MatStencil_c, 1) = c
6536     etc
6537 .ve
6538 
6539 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6540           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6541 @*/
6542 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6543 {
6544   PetscInt  dim    = mat->stencil.dim;
6545   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6546   PetscInt *dims   = mat->stencil.dims + 1;
6547   PetscInt *starts = mat->stencil.starts;
6548   PetscInt *dxm    = (PetscInt *)rows;
6549   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6550 
6551   PetscFunctionBegin;
6552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6553   PetscValidType(mat, 1);
6554   if (numRows) PetscAssertPointer(rows, 3);
6555 
6556   PetscCall(PetscMalloc1(numRows, &jdxm));
6557   for (i = 0; i < numRows; ++i) {
6558     /* Skip unused dimensions (they are ordered k, j, i, c) */
6559     for (j = 0; j < 3 - sdim; ++j) dxm++;
6560     /* Local index in X dir */
6561     tmp = *dxm++ - starts[0];
6562     /* Loop over remaining dimensions */
6563     for (j = 0; j < dim - 1; ++j) {
6564       /* If nonlocal, set index to be negative */
6565       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_INT_MIN;
6566       /* Update local index */
6567       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6568     }
6569     /* Skip component slot if necessary */
6570     if (mat->stencil.noc) dxm++;
6571     /* Local row number */
6572     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6573   }
6574   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6575   PetscCall(PetscFree(jdxm));
6576   PetscFunctionReturn(PETSC_SUCCESS);
6577 }
6578 
6579 /*@
6580   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6581   of a set of rows of a matrix; using local numbering of rows.
6582 
6583   Collective
6584 
6585   Input Parameters:
6586 + mat     - the matrix
6587 . numRows - the number of rows to remove
6588 . rows    - the local row indices
6589 . diag    - value put in all diagonals of eliminated rows
6590 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6591 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6592 
6593   Level: intermediate
6594 
6595   Notes:
6596   Before calling `MatZeroRowsLocal()`, the user must first set the
6597   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6598 
6599   See `MatZeroRows()` for details on how this routine operates.
6600 
6601 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6602           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6603 @*/
6604 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6605 {
6606   PetscFunctionBegin;
6607   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6608   PetscValidType(mat, 1);
6609   if (numRows) PetscAssertPointer(rows, 3);
6610   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6611   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6612   MatCheckPreallocated(mat, 1);
6613 
6614   if (mat->ops->zerorowslocal) {
6615     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6616   } else {
6617     IS              is, newis;
6618     const PetscInt *newRows;
6619 
6620     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6621     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6622     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6623     PetscCall(ISGetIndices(newis, &newRows));
6624     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6625     PetscCall(ISRestoreIndices(newis, &newRows));
6626     PetscCall(ISDestroy(&newis));
6627     PetscCall(ISDestroy(&is));
6628   }
6629   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6630   PetscFunctionReturn(PETSC_SUCCESS);
6631 }
6632 
6633 /*@
6634   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6635   of a set of rows of a matrix; using local numbering of rows.
6636 
6637   Collective
6638 
6639   Input Parameters:
6640 + mat  - the matrix
6641 . is   - index set of rows to remove
6642 . diag - value put in all diagonals of eliminated rows
6643 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6644 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6645 
6646   Level: intermediate
6647 
6648   Notes:
6649   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6650   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6651 
6652   See `MatZeroRows()` for details on how this routine operates.
6653 
6654 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6655           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6656 @*/
6657 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6658 {
6659   PetscInt        numRows;
6660   const PetscInt *rows;
6661 
6662   PetscFunctionBegin;
6663   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6664   PetscValidType(mat, 1);
6665   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6666   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6667   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6668   MatCheckPreallocated(mat, 1);
6669 
6670   PetscCall(ISGetLocalSize(is, &numRows));
6671   PetscCall(ISGetIndices(is, &rows));
6672   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6673   PetscCall(ISRestoreIndices(is, &rows));
6674   PetscFunctionReturn(PETSC_SUCCESS);
6675 }
6676 
6677 /*@
6678   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6679   of a set of rows and columns of a matrix; using local numbering of rows.
6680 
6681   Collective
6682 
6683   Input Parameters:
6684 + mat     - the matrix
6685 . numRows - the number of rows to remove
6686 . rows    - the global row indices
6687 . diag    - value put in all diagonals of eliminated rows
6688 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6689 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6690 
6691   Level: intermediate
6692 
6693   Notes:
6694   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6695   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6696 
6697   See `MatZeroRowsColumns()` for details on how this routine operates.
6698 
6699 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6700           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6701 @*/
6702 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6703 {
6704   IS              is, newis;
6705   const PetscInt *newRows;
6706 
6707   PetscFunctionBegin;
6708   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6709   PetscValidType(mat, 1);
6710   if (numRows) PetscAssertPointer(rows, 3);
6711   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6712   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6713   MatCheckPreallocated(mat, 1);
6714 
6715   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6716   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6717   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6718   PetscCall(ISGetIndices(newis, &newRows));
6719   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6720   PetscCall(ISRestoreIndices(newis, &newRows));
6721   PetscCall(ISDestroy(&newis));
6722   PetscCall(ISDestroy(&is));
6723   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6724   PetscFunctionReturn(PETSC_SUCCESS);
6725 }
6726 
6727 /*@
6728   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6729   of a set of rows and columns of a matrix; using local numbering of rows.
6730 
6731   Collective
6732 
6733   Input Parameters:
6734 + mat  - the matrix
6735 . is   - index set of rows to remove
6736 . diag - value put in all diagonals of eliminated rows
6737 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6738 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6739 
6740   Level: intermediate
6741 
6742   Notes:
6743   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6744   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6745 
6746   See `MatZeroRowsColumns()` for details on how this routine operates.
6747 
6748 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6749           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6750 @*/
6751 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6752 {
6753   PetscInt        numRows;
6754   const PetscInt *rows;
6755 
6756   PetscFunctionBegin;
6757   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6758   PetscValidType(mat, 1);
6759   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6760   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6761   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6762   MatCheckPreallocated(mat, 1);
6763 
6764   PetscCall(ISGetLocalSize(is, &numRows));
6765   PetscCall(ISGetIndices(is, &rows));
6766   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6767   PetscCall(ISRestoreIndices(is, &rows));
6768   PetscFunctionReturn(PETSC_SUCCESS);
6769 }
6770 
6771 /*@
6772   MatGetSize - Returns the numbers of rows and columns in a matrix.
6773 
6774   Not Collective
6775 
6776   Input Parameter:
6777 . mat - the matrix
6778 
6779   Output Parameters:
6780 + m - the number of global rows
6781 - n - the number of global columns
6782 
6783   Level: beginner
6784 
6785   Note:
6786   Both output parameters can be `NULL` on input.
6787 
6788 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6789 @*/
6790 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6791 {
6792   PetscFunctionBegin;
6793   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6794   if (m) *m = mat->rmap->N;
6795   if (n) *n = mat->cmap->N;
6796   PetscFunctionReturn(PETSC_SUCCESS);
6797 }
6798 
6799 /*@
6800   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6801   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6802 
6803   Not Collective
6804 
6805   Input Parameter:
6806 . mat - the matrix
6807 
6808   Output Parameters:
6809 + m - the number of local rows, use `NULL` to not obtain this value
6810 - n - the number of local columns, use `NULL` to not obtain this value
6811 
6812   Level: beginner
6813 
6814 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6815 @*/
6816 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6817 {
6818   PetscFunctionBegin;
6819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6820   if (m) PetscAssertPointer(m, 2);
6821   if (n) PetscAssertPointer(n, 3);
6822   if (m) *m = mat->rmap->n;
6823   if (n) *n = mat->cmap->n;
6824   PetscFunctionReturn(PETSC_SUCCESS);
6825 }
6826 
6827 /*@
6828   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6829   vector one multiplies this matrix by that are owned by this processor.
6830 
6831   Not Collective, unless matrix has not been allocated, then collective
6832 
6833   Input Parameter:
6834 . mat - the matrix
6835 
6836   Output Parameters:
6837 + m - the global index of the first local column, use `NULL` to not obtain this value
6838 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6839 
6840   Level: developer
6841 
6842   Notes:
6843   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6844 
6845   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6846   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6847 
6848   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6849   the local values in the matrix.
6850 
6851   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6852   Layouts](sec_matlayout) for details on matrix layouts.
6853 
6854 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6855           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6856 @*/
6857 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6858 {
6859   PetscFunctionBegin;
6860   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6861   PetscValidType(mat, 1);
6862   if (m) PetscAssertPointer(m, 2);
6863   if (n) PetscAssertPointer(n, 3);
6864   MatCheckPreallocated(mat, 1);
6865   if (m) *m = mat->cmap->rstart;
6866   if (n) *n = mat->cmap->rend;
6867   PetscFunctionReturn(PETSC_SUCCESS);
6868 }
6869 
6870 /*@
6871   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6872   this MPI process.
6873 
6874   Not Collective
6875 
6876   Input Parameter:
6877 . mat - the matrix
6878 
6879   Output Parameters:
6880 + m - the global index of the first local row, use `NULL` to not obtain this value
6881 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6882 
6883   Level: beginner
6884 
6885   Notes:
6886   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6887 
6888   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6889   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6890 
6891   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6892   the local values in the matrix.
6893 
6894   The high argument is one more than the last element stored locally.
6895 
6896   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6897   would contain the result of a matrix vector product with this matrix. See [Matrix
6898   Layouts](sec_matlayout) for details on matrix layouts.
6899 
6900 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6901           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6902 @*/
6903 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6904 {
6905   PetscFunctionBegin;
6906   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6907   PetscValidType(mat, 1);
6908   if (m) PetscAssertPointer(m, 2);
6909   if (n) PetscAssertPointer(n, 3);
6910   MatCheckPreallocated(mat, 1);
6911   if (m) *m = mat->rmap->rstart;
6912   if (n) *n = mat->rmap->rend;
6913   PetscFunctionReturn(PETSC_SUCCESS);
6914 }
6915 
6916 /*@C
6917   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6918   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6919 
6920   Not Collective, unless matrix has not been allocated
6921 
6922   Input Parameter:
6923 . mat - the matrix
6924 
6925   Output Parameter:
6926 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6927            where `size` is the number of MPI processes used by `mat`
6928 
6929   Level: beginner
6930 
6931   Notes:
6932   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6933 
6934   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6935   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6936 
6937   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6938   the local values in the matrix.
6939 
6940   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6941   would contain the result of a matrix vector product with this matrix. See [Matrix
6942   Layouts](sec_matlayout) for details on matrix layouts.
6943 
6944 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6945           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6946           `DMDAGetGhostCorners()`, `DM`
6947 @*/
6948 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6949 {
6950   PetscFunctionBegin;
6951   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6952   PetscValidType(mat, 1);
6953   MatCheckPreallocated(mat, 1);
6954   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6955   PetscFunctionReturn(PETSC_SUCCESS);
6956 }
6957 
6958 /*@C
6959   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6960   vector one multiplies this vector by that are owned by each processor.
6961 
6962   Not Collective, unless matrix has not been allocated
6963 
6964   Input Parameter:
6965 . mat - the matrix
6966 
6967   Output Parameter:
6968 . ranges - start of each processors portion plus one more than the total length at the end
6969 
6970   Level: beginner
6971 
6972   Notes:
6973   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6974 
6975   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6976   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6977 
6978   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6979   the local values in the matrix.
6980 
6981   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6982   Layouts](sec_matlayout) for details on matrix layouts.
6983 
6984 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
6985           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
6986           `DMDAGetGhostCorners()`, `DM`
6987 @*/
6988 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
6989 {
6990   PetscFunctionBegin;
6991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6992   PetscValidType(mat, 1);
6993   MatCheckPreallocated(mat, 1);
6994   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6995   PetscFunctionReturn(PETSC_SUCCESS);
6996 }
6997 
6998 /*@
6999   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7000 
7001   Not Collective
7002 
7003   Input Parameter:
7004 . A - matrix
7005 
7006   Output Parameters:
7007 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7008 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7009 
7010   Level: intermediate
7011 
7012   Note:
7013   You should call `ISDestroy()` on the returned `IS`
7014 
7015   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7016   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7017   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7018   details on matrix layouts.
7019 
7020 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7021 @*/
7022 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7023 {
7024   PetscErrorCode (*f)(Mat, IS *, IS *);
7025 
7026   PetscFunctionBegin;
7027   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7028   PetscValidType(A, 1);
7029   MatCheckPreallocated(A, 1);
7030   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7031   if (f) {
7032     PetscCall((*f)(A, rows, cols));
7033   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7034     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7035     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7036   }
7037   PetscFunctionReturn(PETSC_SUCCESS);
7038 }
7039 
7040 /*@
7041   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7042   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7043   to complete the factorization.
7044 
7045   Collective
7046 
7047   Input Parameters:
7048 + fact - the factorized matrix obtained with `MatGetFactor()`
7049 . mat  - the matrix
7050 . row  - row permutation
7051 . col  - column permutation
7052 - info - structure containing
7053 .vb
7054       levels - number of levels of fill.
7055       expected fill - as ratio of original fill.
7056       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7057                 missing diagonal entries)
7058 .ve
7059 
7060   Level: developer
7061 
7062   Notes:
7063   See [Matrix Factorization](sec_matfactor) for additional information.
7064 
7065   Most users should employ the `KSP` interface for linear solvers
7066   instead of working directly with matrix algebra routines such as this.
7067   See, e.g., `KSPCreate()`.
7068 
7069   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7070 
7071   Developer Note:
7072   The Fortran interface is not autogenerated as the
7073   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7074 
7075 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7076           `MatGetOrdering()`, `MatFactorInfo`
7077 @*/
7078 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7079 {
7080   PetscFunctionBegin;
7081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7082   PetscValidType(mat, 2);
7083   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7084   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7085   PetscAssertPointer(info, 5);
7086   PetscAssertPointer(fact, 1);
7087   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7088   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7089   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7090   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7091   MatCheckPreallocated(mat, 2);
7092 
7093   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7094   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7095   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7096   PetscFunctionReturn(PETSC_SUCCESS);
7097 }
7098 
7099 /*@
7100   MatICCFactorSymbolic - Performs symbolic incomplete
7101   Cholesky factorization for a symmetric matrix.  Use
7102   `MatCholeskyFactorNumeric()` to complete the factorization.
7103 
7104   Collective
7105 
7106   Input Parameters:
7107 + fact - the factorized matrix obtained with `MatGetFactor()`
7108 . mat  - the matrix to be factored
7109 . perm - row and column permutation
7110 - info - structure containing
7111 .vb
7112       levels - number of levels of fill.
7113       expected fill - as ratio of original fill.
7114 .ve
7115 
7116   Level: developer
7117 
7118   Notes:
7119   Most users should employ the `KSP` interface for linear solvers
7120   instead of working directly with matrix algebra routines such as this.
7121   See, e.g., `KSPCreate()`.
7122 
7123   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7124 
7125   Developer Note:
7126   The Fortran interface is not autogenerated as the
7127   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7128 
7129 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7130 @*/
7131 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7132 {
7133   PetscFunctionBegin;
7134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7135   PetscValidType(mat, 2);
7136   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7137   PetscAssertPointer(info, 4);
7138   PetscAssertPointer(fact, 1);
7139   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7140   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7141   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7142   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7143   MatCheckPreallocated(mat, 2);
7144 
7145   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7146   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7147   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7148   PetscFunctionReturn(PETSC_SUCCESS);
7149 }
7150 
7151 /*@C
7152   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7153   points to an array of valid matrices, they may be reused to store the new
7154   submatrices.
7155 
7156   Collective
7157 
7158   Input Parameters:
7159 + mat   - the matrix
7160 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7161 . irow  - index set of rows to extract
7162 . icol  - index set of columns to extract
7163 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7164 
7165   Output Parameter:
7166 . submat - the array of submatrices
7167 
7168   Level: advanced
7169 
7170   Notes:
7171   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7172   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7173   to extract a parallel submatrix.
7174 
7175   Some matrix types place restrictions on the row and column
7176   indices, such as that they be sorted or that they be equal to each other.
7177 
7178   The index sets may not have duplicate entries.
7179 
7180   When extracting submatrices from a parallel matrix, each processor can
7181   form a different submatrix by setting the rows and columns of its
7182   individual index sets according to the local submatrix desired.
7183 
7184   When finished using the submatrices, the user should destroy
7185   them with `MatDestroySubMatrices()`.
7186 
7187   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7188   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7189 
7190   This routine creates the matrices in submat; you should NOT create them before
7191   calling it. It also allocates the array of matrix pointers submat.
7192 
7193   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7194   request one row/column in a block, they must request all rows/columns that are in
7195   that block. For example, if the block size is 2 you cannot request just row 0 and
7196   column 0.
7197 
7198   Fortran Note:
7199   One must pass in as `submat` a `Mat` array of size at least `n`+1.
7200 
7201 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7202 @*/
7203 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7204 {
7205   PetscInt  i;
7206   PetscBool eq;
7207 
7208   PetscFunctionBegin;
7209   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7210   PetscValidType(mat, 1);
7211   if (n) {
7212     PetscAssertPointer(irow, 3);
7213     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7214     PetscAssertPointer(icol, 4);
7215     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7216   }
7217   PetscAssertPointer(submat, 6);
7218   if (n && scall == MAT_REUSE_MATRIX) {
7219     PetscAssertPointer(*submat, 6);
7220     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7221   }
7222   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7223   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7224   MatCheckPreallocated(mat, 1);
7225   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7226   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7227   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7228   for (i = 0; i < n; i++) {
7229     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7230     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7231     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7232 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7233     if (mat->boundtocpu && mat->bindingpropagates) {
7234       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7235       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7236     }
7237 #endif
7238   }
7239   PetscFunctionReturn(PETSC_SUCCESS);
7240 }
7241 
7242 /*@C
7243   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7244 
7245   Collective
7246 
7247   Input Parameters:
7248 + mat   - the matrix
7249 . n     - the number of submatrixes to be extracted
7250 . irow  - index set of rows to extract
7251 . icol  - index set of columns to extract
7252 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7253 
7254   Output Parameter:
7255 . submat - the array of submatrices
7256 
7257   Level: advanced
7258 
7259   Note:
7260   This is used by `PCGASM`
7261 
7262 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7263 @*/
7264 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7265 {
7266   PetscInt  i;
7267   PetscBool eq;
7268 
7269   PetscFunctionBegin;
7270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7271   PetscValidType(mat, 1);
7272   if (n) {
7273     PetscAssertPointer(irow, 3);
7274     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7275     PetscAssertPointer(icol, 4);
7276     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7277   }
7278   PetscAssertPointer(submat, 6);
7279   if (n && scall == MAT_REUSE_MATRIX) {
7280     PetscAssertPointer(*submat, 6);
7281     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7282   }
7283   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7284   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7285   MatCheckPreallocated(mat, 1);
7286 
7287   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7288   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7289   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7290   for (i = 0; i < n; i++) {
7291     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7292     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7293   }
7294   PetscFunctionReturn(PETSC_SUCCESS);
7295 }
7296 
7297 /*@C
7298   MatDestroyMatrices - Destroys an array of matrices.
7299 
7300   Collective
7301 
7302   Input Parameters:
7303 + n   - the number of local matrices
7304 - mat - the matrices (this is a pointer to the array of matrices)
7305 
7306   Level: advanced
7307 
7308   Notes:
7309   Frees not only the matrices, but also the array that contains the matrices
7310 
7311   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7312 
7313   Fortran Note:
7314   Does not free the `mat` array.
7315 
7316 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7317 @*/
7318 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7319 {
7320   PetscInt i;
7321 
7322   PetscFunctionBegin;
7323   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7324   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7325   PetscAssertPointer(mat, 2);
7326 
7327   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7328 
7329   /* memory is allocated even if n = 0 */
7330   PetscCall(PetscFree(*mat));
7331   PetscFunctionReturn(PETSC_SUCCESS);
7332 }
7333 
7334 /*@C
7335   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7336 
7337   Collective
7338 
7339   Input Parameters:
7340 + n   - the number of local matrices
7341 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7342                        sequence of `MatCreateSubMatrices()`)
7343 
7344   Level: advanced
7345 
7346   Note:
7347   Frees not only the matrices, but also the array that contains the matrices
7348 
7349   Fortran Note:
7350   Does not free the `mat` array.
7351 
7352 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7353 @*/
7354 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7355 {
7356   Mat mat0;
7357 
7358   PetscFunctionBegin;
7359   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7360   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7361   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7362   PetscAssertPointer(mat, 2);
7363 
7364   mat0 = (*mat)[0];
7365   if (mat0 && mat0->ops->destroysubmatrices) {
7366     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7367   } else {
7368     PetscCall(MatDestroyMatrices(n, mat));
7369   }
7370   PetscFunctionReturn(PETSC_SUCCESS);
7371 }
7372 
7373 /*@
7374   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7375 
7376   Collective
7377 
7378   Input Parameter:
7379 . mat - the matrix
7380 
7381   Output Parameter:
7382 . matstruct - the sequential matrix with the nonzero structure of `mat`
7383 
7384   Level: developer
7385 
7386 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7387 @*/
7388 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7389 {
7390   PetscFunctionBegin;
7391   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7392   PetscAssertPointer(matstruct, 2);
7393 
7394   PetscValidType(mat, 1);
7395   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7396   MatCheckPreallocated(mat, 1);
7397 
7398   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7399   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7400   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7401   PetscFunctionReturn(PETSC_SUCCESS);
7402 }
7403 
7404 /*@C
7405   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7406 
7407   Collective
7408 
7409   Input Parameter:
7410 . mat - the matrix
7411 
7412   Level: advanced
7413 
7414   Note:
7415   This is not needed, one can just call `MatDestroy()`
7416 
7417 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7418 @*/
7419 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7420 {
7421   PetscFunctionBegin;
7422   PetscAssertPointer(mat, 1);
7423   PetscCall(MatDestroy(mat));
7424   PetscFunctionReturn(PETSC_SUCCESS);
7425 }
7426 
7427 /*@
7428   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7429   replaces the index sets by larger ones that represent submatrices with
7430   additional overlap.
7431 
7432   Collective
7433 
7434   Input Parameters:
7435 + mat - the matrix
7436 . n   - the number of index sets
7437 . is  - the array of index sets (these index sets will changed during the call)
7438 - ov  - the additional overlap requested
7439 
7440   Options Database Key:
7441 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7442 
7443   Level: developer
7444 
7445   Note:
7446   The computed overlap preserves the matrix block sizes when the blocks are square.
7447   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7448   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7449 
7450 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7451 @*/
7452 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7453 {
7454   PetscInt i, bs, cbs;
7455 
7456   PetscFunctionBegin;
7457   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7458   PetscValidType(mat, 1);
7459   PetscValidLogicalCollectiveInt(mat, n, 2);
7460   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7461   if (n) {
7462     PetscAssertPointer(is, 3);
7463     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7464   }
7465   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7466   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7467   MatCheckPreallocated(mat, 1);
7468 
7469   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7470   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7471   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7472   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7473   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7474   if (bs == cbs) {
7475     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7476   }
7477   PetscFunctionReturn(PETSC_SUCCESS);
7478 }
7479 
7480 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7481 
7482 /*@
7483   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7484   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7485   additional overlap.
7486 
7487   Collective
7488 
7489   Input Parameters:
7490 + mat - the matrix
7491 . n   - the number of index sets
7492 . is  - the array of index sets (these index sets will changed during the call)
7493 - ov  - the additional overlap requested
7494 
7495   `   Options Database Key:
7496 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7497 
7498   Level: developer
7499 
7500 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7501 @*/
7502 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7503 {
7504   PetscInt i;
7505 
7506   PetscFunctionBegin;
7507   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7508   PetscValidType(mat, 1);
7509   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7510   if (n) {
7511     PetscAssertPointer(is, 3);
7512     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7513   }
7514   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7515   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7516   MatCheckPreallocated(mat, 1);
7517   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7518   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7519   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7520   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7521   PetscFunctionReturn(PETSC_SUCCESS);
7522 }
7523 
7524 /*@
7525   MatGetBlockSize - Returns the matrix block size.
7526 
7527   Not Collective
7528 
7529   Input Parameter:
7530 . mat - the matrix
7531 
7532   Output Parameter:
7533 . bs - block size
7534 
7535   Level: intermediate
7536 
7537   Notes:
7538   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7539 
7540   If the block size has not been set yet this routine returns 1.
7541 
7542 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7543 @*/
7544 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7545 {
7546   PetscFunctionBegin;
7547   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7548   PetscAssertPointer(bs, 2);
7549   *bs = PetscAbs(mat->rmap->bs);
7550   PetscFunctionReturn(PETSC_SUCCESS);
7551 }
7552 
7553 /*@
7554   MatGetBlockSizes - Returns the matrix block row and column sizes.
7555 
7556   Not Collective
7557 
7558   Input Parameter:
7559 . mat - the matrix
7560 
7561   Output Parameters:
7562 + rbs - row block size
7563 - cbs - column block size
7564 
7565   Level: intermediate
7566 
7567   Notes:
7568   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7569   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7570 
7571   If a block size has not been set yet this routine returns 1.
7572 
7573 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7574 @*/
7575 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7576 {
7577   PetscFunctionBegin;
7578   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7579   if (rbs) PetscAssertPointer(rbs, 2);
7580   if (cbs) PetscAssertPointer(cbs, 3);
7581   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7582   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7583   PetscFunctionReturn(PETSC_SUCCESS);
7584 }
7585 
7586 /*@
7587   MatSetBlockSize - Sets the matrix block size.
7588 
7589   Logically Collective
7590 
7591   Input Parameters:
7592 + mat - the matrix
7593 - bs  - block size
7594 
7595   Level: intermediate
7596 
7597   Notes:
7598   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7599   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7600 
7601   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7602   is compatible with the matrix local sizes.
7603 
7604 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7605 @*/
7606 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7607 {
7608   PetscFunctionBegin;
7609   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7610   PetscValidLogicalCollectiveInt(mat, bs, 2);
7611   PetscCall(MatSetBlockSizes(mat, bs, bs));
7612   PetscFunctionReturn(PETSC_SUCCESS);
7613 }
7614 
7615 typedef struct {
7616   PetscInt         n;
7617   IS              *is;
7618   Mat             *mat;
7619   PetscObjectState nonzerostate;
7620   Mat              C;
7621 } EnvelopeData;
7622 
7623 static PetscErrorCode EnvelopeDataDestroy(void *ptr)
7624 {
7625   EnvelopeData *edata = (EnvelopeData *)ptr;
7626 
7627   PetscFunctionBegin;
7628   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7629   PetscCall(PetscFree(edata->is));
7630   PetscCall(PetscFree(edata));
7631   PetscFunctionReturn(PETSC_SUCCESS);
7632 }
7633 
7634 /*@
7635   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7636   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7637 
7638   Collective
7639 
7640   Input Parameter:
7641 . mat - the matrix
7642 
7643   Level: intermediate
7644 
7645   Notes:
7646   There can be zeros within the blocks
7647 
7648   The blocks can overlap between processes, including laying on more than two processes
7649 
7650 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7651 @*/
7652 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7653 {
7654   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7655   PetscInt          *diag, *odiag, sc;
7656   VecScatter         scatter;
7657   PetscScalar       *seqv;
7658   const PetscScalar *parv;
7659   const PetscInt    *ia, *ja;
7660   PetscBool          set, flag, done;
7661   Mat                AA = mat, A;
7662   MPI_Comm           comm;
7663   PetscMPIInt        rank, size, tag;
7664   MPI_Status         status;
7665   PetscContainer     container;
7666   EnvelopeData      *edata;
7667   Vec                seq, par;
7668   IS                 isglobal;
7669 
7670   PetscFunctionBegin;
7671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7672   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7673   if (!set || !flag) {
7674     /* TODO: only needs nonzero structure of transpose */
7675     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7676     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7677   }
7678   PetscCall(MatAIJGetLocalMat(AA, &A));
7679   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7680   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7681 
7682   PetscCall(MatGetLocalSize(mat, &n, NULL));
7683   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7684   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7685   PetscCallMPI(MPI_Comm_size(comm, &size));
7686   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7687 
7688   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7689 
7690   if (rank > 0) {
7691     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7692     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7693   }
7694   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7695   for (i = 0; i < n; i++) {
7696     env = PetscMax(env, ja[ia[i + 1] - 1]);
7697     II  = rstart + i;
7698     if (env == II) {
7699       starts[lblocks]  = tbs;
7700       sizes[lblocks++] = 1 + II - tbs;
7701       tbs              = 1 + II;
7702     }
7703   }
7704   if (rank < size - 1) {
7705     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7706     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7707   }
7708 
7709   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7710   if (!set || !flag) PetscCall(MatDestroy(&AA));
7711   PetscCall(MatDestroy(&A));
7712 
7713   PetscCall(PetscNew(&edata));
7714   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7715   edata->n = lblocks;
7716   /* create IS needed for extracting blocks from the original matrix */
7717   PetscCall(PetscMalloc1(lblocks, &edata->is));
7718   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7719 
7720   /* Create the resulting inverse matrix nonzero structure with preallocation information */
7721   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7722   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7723   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7724   PetscCall(MatSetType(edata->C, MATAIJ));
7725 
7726   /* Communicate the start and end of each row, from each block to the correct rank */
7727   /* TODO: Use PetscSF instead of VecScatter */
7728   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7729   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7730   PetscCall(VecGetArrayWrite(seq, &seqv));
7731   for (PetscInt i = 0; i < lblocks; i++) {
7732     for (PetscInt j = 0; j < sizes[i]; j++) {
7733       seqv[cnt]     = starts[i];
7734       seqv[cnt + 1] = starts[i] + sizes[i];
7735       cnt += 2;
7736     }
7737   }
7738   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7739   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7740   sc -= cnt;
7741   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7742   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7743   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7744   PetscCall(ISDestroy(&isglobal));
7745   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7746   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7747   PetscCall(VecScatterDestroy(&scatter));
7748   PetscCall(VecDestroy(&seq));
7749   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7750   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7751   PetscCall(VecGetArrayRead(par, &parv));
7752   cnt = 0;
7753   PetscCall(MatGetSize(mat, NULL, &n));
7754   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7755     PetscInt start, end, d = 0, od = 0;
7756 
7757     start = (PetscInt)PetscRealPart(parv[cnt]);
7758     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7759     cnt += 2;
7760 
7761     if (start < cstart) {
7762       od += cstart - start + n - cend;
7763       d += cend - cstart;
7764     } else if (start < cend) {
7765       od += n - cend;
7766       d += cend - start;
7767     } else od += n - start;
7768     if (end <= cstart) {
7769       od -= cstart - end + n - cend;
7770       d -= cend - cstart;
7771     } else if (end < cend) {
7772       od -= n - cend;
7773       d -= cend - end;
7774     } else od -= n - end;
7775 
7776     odiag[i] = od;
7777     diag[i]  = d;
7778   }
7779   PetscCall(VecRestoreArrayRead(par, &parv));
7780   PetscCall(VecDestroy(&par));
7781   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7782   PetscCall(PetscFree2(diag, odiag));
7783   PetscCall(PetscFree2(sizes, starts));
7784 
7785   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7786   PetscCall(PetscContainerSetPointer(container, edata));
7787   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode (*)(void *))EnvelopeDataDestroy));
7788   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7789   PetscCall(PetscObjectDereference((PetscObject)container));
7790   PetscFunctionReturn(PETSC_SUCCESS);
7791 }
7792 
7793 /*@
7794   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7795 
7796   Collective
7797 
7798   Input Parameters:
7799 + A     - the matrix
7800 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7801 
7802   Output Parameter:
7803 . C - matrix with inverted block diagonal of `A`
7804 
7805   Level: advanced
7806 
7807   Note:
7808   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7809 
7810 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7811 @*/
7812 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7813 {
7814   PetscContainer   container;
7815   EnvelopeData    *edata;
7816   PetscObjectState nonzerostate;
7817 
7818   PetscFunctionBegin;
7819   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7820   if (!container) {
7821     PetscCall(MatComputeVariableBlockEnvelope(A));
7822     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7823   }
7824   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7825   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7826   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7827   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7828 
7829   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7830   *C = edata->C;
7831 
7832   for (PetscInt i = 0; i < edata->n; i++) {
7833     Mat          D;
7834     PetscScalar *dvalues;
7835 
7836     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7837     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7838     PetscCall(MatSeqDenseInvert(D));
7839     PetscCall(MatDenseGetArray(D, &dvalues));
7840     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7841     PetscCall(MatDestroy(&D));
7842   }
7843   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7844   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7845   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7846   PetscFunctionReturn(PETSC_SUCCESS);
7847 }
7848 
7849 /*@
7850   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7851 
7852   Not Collective
7853 
7854   Input Parameters:
7855 + mat     - the matrix
7856 . nblocks - the number of blocks on this process, each block can only exist on a single process
7857 - bsizes  - the block sizes
7858 
7859   Level: intermediate
7860 
7861   Notes:
7862   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7863 
7864   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.
7865 
7866 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7867           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7868 @*/
7869 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7870 {
7871   PetscInt ncnt = 0, nlocal;
7872 
7873   PetscFunctionBegin;
7874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7875   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7876   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);
7877   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7878   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);
7879   PetscCall(PetscFree(mat->bsizes));
7880   mat->nblocks = nblocks;
7881   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7882   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7883   PetscFunctionReturn(PETSC_SUCCESS);
7884 }
7885 
7886 /*@C
7887   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7888 
7889   Not Collective; No Fortran Support
7890 
7891   Input Parameter:
7892 . mat - the matrix
7893 
7894   Output Parameters:
7895 + nblocks - the number of blocks on this process
7896 - bsizes  - the block sizes
7897 
7898   Level: intermediate
7899 
7900 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7901 @*/
7902 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7903 {
7904   PetscFunctionBegin;
7905   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7906   if (nblocks) *nblocks = mat->nblocks;
7907   if (bsizes) *bsizes = mat->bsizes;
7908   PetscFunctionReturn(PETSC_SUCCESS);
7909 }
7910 
7911 /*@
7912   MatSetBlockSizes - Sets the matrix block row and column sizes.
7913 
7914   Logically Collective
7915 
7916   Input Parameters:
7917 + mat - the matrix
7918 . rbs - row block size
7919 - cbs - column block size
7920 
7921   Level: intermediate
7922 
7923   Notes:
7924   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7925   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7926   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7927 
7928   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7929   are compatible with the matrix local sizes.
7930 
7931   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7932 
7933 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7934 @*/
7935 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7936 {
7937   PetscFunctionBegin;
7938   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7939   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7940   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7941   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7942   if (mat->rmap->refcnt) {
7943     ISLocalToGlobalMapping l2g  = NULL;
7944     PetscLayout            nmap = NULL;
7945 
7946     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7947     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7948     PetscCall(PetscLayoutDestroy(&mat->rmap));
7949     mat->rmap          = nmap;
7950     mat->rmap->mapping = l2g;
7951   }
7952   if (mat->cmap->refcnt) {
7953     ISLocalToGlobalMapping l2g  = NULL;
7954     PetscLayout            nmap = NULL;
7955 
7956     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7957     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7958     PetscCall(PetscLayoutDestroy(&mat->cmap));
7959     mat->cmap          = nmap;
7960     mat->cmap->mapping = l2g;
7961   }
7962   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7963   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7964   PetscFunctionReturn(PETSC_SUCCESS);
7965 }
7966 
7967 /*@
7968   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7969 
7970   Logically Collective
7971 
7972   Input Parameters:
7973 + mat     - the matrix
7974 . fromRow - matrix from which to copy row block size
7975 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7976 
7977   Level: developer
7978 
7979 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7980 @*/
7981 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7982 {
7983   PetscFunctionBegin;
7984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7985   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7986   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7987   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7988   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7989   PetscFunctionReturn(PETSC_SUCCESS);
7990 }
7991 
7992 /*@
7993   MatResidual - Default routine to calculate the residual r = b - Ax
7994 
7995   Collective
7996 
7997   Input Parameters:
7998 + mat - the matrix
7999 . b   - the right-hand-side
8000 - x   - the approximate solution
8001 
8002   Output Parameter:
8003 . r - location to store the residual
8004 
8005   Level: developer
8006 
8007 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8008 @*/
8009 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8010 {
8011   PetscFunctionBegin;
8012   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8013   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8014   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8015   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8016   PetscValidType(mat, 1);
8017   MatCheckPreallocated(mat, 1);
8018   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8019   if (!mat->ops->residual) {
8020     PetscCall(MatMult(mat, x, r));
8021     PetscCall(VecAYPX(r, -1.0, b));
8022   } else {
8023     PetscUseTypeMethod(mat, residual, b, x, r);
8024   }
8025   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8026   PetscFunctionReturn(PETSC_SUCCESS);
8027 }
8028 
8029 /*MC
8030     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
8031 
8032     Synopsis:
8033     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8034 
8035     Not Collective
8036 
8037     Input Parameters:
8038 +   A - the matrix
8039 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8040 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8041 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8042                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8043                  always used.
8044 
8045     Output Parameters:
8046 +   n - number of local rows in the (possibly compressed) matrix
8047 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8048 .   ja - the column indices
8049 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8050            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8051 
8052     Level: developer
8053 
8054     Note:
8055     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
8056 
8057 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
8058 M*/
8059 
8060 /*MC
8061     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
8062 
8063     Synopsis:
8064     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8065 
8066     Not Collective
8067 
8068     Input Parameters:
8069 +   A - the  matrix
8070 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8071 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8072     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8073                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8074                  always used.
8075 .   n - number of local rows in the (possibly compressed) matrix
8076 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8077 .   ja - the column indices
8078 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8079            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8080 
8081     Level: developer
8082 
8083 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
8084 M*/
8085 
8086 /*@C
8087   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8088 
8089   Collective
8090 
8091   Input Parameters:
8092 + mat             - the matrix
8093 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8094 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8095 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8096                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8097                  always used.
8098 
8099   Output Parameters:
8100 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8101 . 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
8102 . ja   - the column indices, use `NULL` if not needed
8103 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8104            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8105 
8106   Level: developer
8107 
8108   Notes:
8109   You CANNOT change any of the ia[] or ja[] values.
8110 
8111   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8112 
8113   Fortran Notes:
8114   Use
8115 .vb
8116     PetscInt, pointer :: ia(:),ja(:)
8117     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8118     ! Access the ith and jth entries via ia(i) and ja(j)
8119 .ve
8120 
8121   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8122 
8123 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8124 @*/
8125 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8126 {
8127   PetscFunctionBegin;
8128   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8129   PetscValidType(mat, 1);
8130   if (n) PetscAssertPointer(n, 5);
8131   if (ia) PetscAssertPointer(ia, 6);
8132   if (ja) PetscAssertPointer(ja, 7);
8133   if (done) PetscAssertPointer(done, 8);
8134   MatCheckPreallocated(mat, 1);
8135   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8136   else {
8137     if (done) *done = PETSC_TRUE;
8138     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8139     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8140     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8141   }
8142   PetscFunctionReturn(PETSC_SUCCESS);
8143 }
8144 
8145 /*@C
8146   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8147 
8148   Collective
8149 
8150   Input Parameters:
8151 + mat             - the matrix
8152 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8153 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8154                 symmetrized
8155 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8156                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8157                  always used.
8158 . n               - number of columns in the (possibly compressed) matrix
8159 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8160 - ja              - the row indices
8161 
8162   Output Parameter:
8163 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8164 
8165   Level: developer
8166 
8167 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8168 @*/
8169 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8170 {
8171   PetscFunctionBegin;
8172   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8173   PetscValidType(mat, 1);
8174   PetscAssertPointer(n, 5);
8175   if (ia) PetscAssertPointer(ia, 6);
8176   if (ja) PetscAssertPointer(ja, 7);
8177   PetscAssertPointer(done, 8);
8178   MatCheckPreallocated(mat, 1);
8179   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8180   else {
8181     *done = PETSC_TRUE;
8182     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8183   }
8184   PetscFunctionReturn(PETSC_SUCCESS);
8185 }
8186 
8187 /*@C
8188   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8189 
8190   Collective
8191 
8192   Input Parameters:
8193 + mat             - the matrix
8194 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8195 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8196 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8197                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8198                     always used.
8199 . n               - size of (possibly compressed) matrix
8200 . ia              - the row pointers
8201 - ja              - the column indices
8202 
8203   Output Parameter:
8204 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8205 
8206   Level: developer
8207 
8208   Note:
8209   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8210   us of the array after it has been restored. If you pass `NULL`, it will
8211   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8212 
8213   Fortran Note:
8214   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8215 
8216 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8217 @*/
8218 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8219 {
8220   PetscFunctionBegin;
8221   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8222   PetscValidType(mat, 1);
8223   if (ia) PetscAssertPointer(ia, 6);
8224   if (ja) PetscAssertPointer(ja, 7);
8225   if (done) PetscAssertPointer(done, 8);
8226   MatCheckPreallocated(mat, 1);
8227 
8228   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8229   else {
8230     if (done) *done = PETSC_TRUE;
8231     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8232     if (n) *n = 0;
8233     if (ia) *ia = NULL;
8234     if (ja) *ja = NULL;
8235   }
8236   PetscFunctionReturn(PETSC_SUCCESS);
8237 }
8238 
8239 /*@C
8240   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8241 
8242   Collective
8243 
8244   Input Parameters:
8245 + mat             - the matrix
8246 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8247 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8248 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8249                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8250                     always used.
8251 
8252   Output Parameters:
8253 + n    - size of (possibly compressed) matrix
8254 . ia   - the column pointers
8255 . ja   - the row indices
8256 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8257 
8258   Level: developer
8259 
8260 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8261 @*/
8262 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8263 {
8264   PetscFunctionBegin;
8265   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8266   PetscValidType(mat, 1);
8267   if (ia) PetscAssertPointer(ia, 6);
8268   if (ja) PetscAssertPointer(ja, 7);
8269   PetscAssertPointer(done, 8);
8270   MatCheckPreallocated(mat, 1);
8271 
8272   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8273   else {
8274     *done = PETSC_TRUE;
8275     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8276     if (n) *n = 0;
8277     if (ia) *ia = NULL;
8278     if (ja) *ja = NULL;
8279   }
8280   PetscFunctionReturn(PETSC_SUCCESS);
8281 }
8282 
8283 /*@
8284   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8285   `MatGetColumnIJ()`.
8286 
8287   Collective
8288 
8289   Input Parameters:
8290 + mat        - the matrix
8291 . ncolors    - maximum color value
8292 . n          - number of entries in colorarray
8293 - colorarray - array indicating color for each column
8294 
8295   Output Parameter:
8296 . iscoloring - coloring generated using colorarray information
8297 
8298   Level: developer
8299 
8300 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8301 @*/
8302 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8303 {
8304   PetscFunctionBegin;
8305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8306   PetscValidType(mat, 1);
8307   PetscAssertPointer(colorarray, 4);
8308   PetscAssertPointer(iscoloring, 5);
8309   MatCheckPreallocated(mat, 1);
8310 
8311   if (!mat->ops->coloringpatch) {
8312     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8313   } else {
8314     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8315   }
8316   PetscFunctionReturn(PETSC_SUCCESS);
8317 }
8318 
8319 /*@
8320   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8321 
8322   Logically Collective
8323 
8324   Input Parameter:
8325 . mat - the factored matrix to be reset
8326 
8327   Level: developer
8328 
8329   Notes:
8330   This routine should be used only with factored matrices formed by in-place
8331   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8332   format).  This option can save memory, for example, when solving nonlinear
8333   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8334   ILU(0) preconditioner.
8335 
8336   One can specify in-place ILU(0) factorization by calling
8337 .vb
8338      PCType(pc,PCILU);
8339      PCFactorSeUseInPlace(pc);
8340 .ve
8341   or by using the options -pc_type ilu -pc_factor_in_place
8342 
8343   In-place factorization ILU(0) can also be used as a local
8344   solver for the blocks within the block Jacobi or additive Schwarz
8345   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8346   for details on setting local solver options.
8347 
8348   Most users should employ the `KSP` interface for linear solvers
8349   instead of working directly with matrix algebra routines such as this.
8350   See, e.g., `KSPCreate()`.
8351 
8352 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8353 @*/
8354 PetscErrorCode MatSetUnfactored(Mat mat)
8355 {
8356   PetscFunctionBegin;
8357   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8358   PetscValidType(mat, 1);
8359   MatCheckPreallocated(mat, 1);
8360   mat->factortype = MAT_FACTOR_NONE;
8361   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8362   PetscUseTypeMethod(mat, setunfactored);
8363   PetscFunctionReturn(PETSC_SUCCESS);
8364 }
8365 
8366 /*MC
8367     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8368 
8369     Synopsis:
8370     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8371 
8372     Not Collective
8373 
8374     Input Parameter:
8375 .   x - matrix
8376 
8377     Output Parameters:
8378 +   xx_v - the Fortran pointer to the array
8379 -   ierr - error code
8380 
8381     Example of Usage:
8382 .vb
8383       PetscScalar, pointer xx_v(:,:)
8384       ....
8385       call MatDenseGetArrayF90(x,xx_v,ierr)
8386       a = xx_v(3)
8387       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8388 .ve
8389 
8390     Level: advanced
8391 
8392 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8393 M*/
8394 
8395 /*MC
8396     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8397     accessed with `MatDenseGetArrayF90()`.
8398 
8399     Synopsis:
8400     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8401 
8402     Not Collective
8403 
8404     Input Parameters:
8405 +   x - matrix
8406 -   xx_v - the Fortran90 pointer to the array
8407 
8408     Output Parameter:
8409 .   ierr - error code
8410 
8411     Example of Usage:
8412 .vb
8413        PetscScalar, pointer xx_v(:,:)
8414        ....
8415        call MatDenseGetArrayF90(x,xx_v,ierr)
8416        a = xx_v(3)
8417        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8418 .ve
8419 
8420     Level: advanced
8421 
8422 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8423 M*/
8424 
8425 /*MC
8426     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8427 
8428     Synopsis:
8429     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8430 
8431     Not Collective
8432 
8433     Input Parameter:
8434 .   x - matrix
8435 
8436     Output Parameters:
8437 +   xx_v - the Fortran pointer to the array
8438 -   ierr - error code
8439 
8440     Example of Usage:
8441 .vb
8442       PetscScalar, pointer xx_v(:)
8443       ....
8444       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8445       a = xx_v(3)
8446       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8447 .ve
8448 
8449     Level: advanced
8450 
8451 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8452 M*/
8453 
8454 /*MC
8455     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8456     accessed with `MatSeqAIJGetArrayF90()`.
8457 
8458     Synopsis:
8459     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8460 
8461     Not Collective
8462 
8463     Input Parameters:
8464 +   x - matrix
8465 -   xx_v - the Fortran90 pointer to the array
8466 
8467     Output Parameter:
8468 .   ierr - error code
8469 
8470     Example of Usage:
8471 .vb
8472        PetscScalar, pointer xx_v(:)
8473        ....
8474        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8475        a = xx_v(3)
8476        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8477 .ve
8478 
8479     Level: advanced
8480 
8481 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8482 M*/
8483 
8484 /*@
8485   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8486   as the original matrix.
8487 
8488   Collective
8489 
8490   Input Parameters:
8491 + mat   - the original matrix
8492 . isrow - parallel `IS` containing the rows this processor should obtain
8493 . 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.
8494 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8495 
8496   Output Parameter:
8497 . newmat - the new submatrix, of the same type as the original matrix
8498 
8499   Level: advanced
8500 
8501   Notes:
8502   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8503 
8504   Some matrix types place restrictions on the row and column indices, such
8505   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;
8506   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8507 
8508   The index sets may not have duplicate entries.
8509 
8510   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8511   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8512   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8513   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8514   you are finished using it.
8515 
8516   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8517   the input matrix.
8518 
8519   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8520 
8521   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8522   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8523 
8524   Example usage:
8525   Consider the following 8x8 matrix with 34 non-zero values, that is
8526   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8527   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8528   as follows
8529 .vb
8530             1  2  0  |  0  3  0  |  0  4
8531     Proc0   0  5  6  |  7  0  0  |  8  0
8532             9  0 10  | 11  0  0  | 12  0
8533     -------------------------------------
8534            13  0 14  | 15 16 17  |  0  0
8535     Proc1   0 18  0  | 19 20 21  |  0  0
8536             0  0  0  | 22 23  0  | 24  0
8537     -------------------------------------
8538     Proc2  25 26 27  |  0  0 28  | 29  0
8539            30  0  0  | 31 32 33  |  0 34
8540 .ve
8541 
8542   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8543 
8544 .vb
8545             2  0  |  0  3  0  |  0
8546     Proc0   5  6  |  7  0  0  |  8
8547     -------------------------------
8548     Proc1  18  0  | 19 20 21  |  0
8549     -------------------------------
8550     Proc2  26 27  |  0  0 28  | 29
8551             0  0  | 31 32 33  |  0
8552 .ve
8553 
8554 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8555 @*/
8556 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8557 {
8558   PetscMPIInt size;
8559   Mat        *local;
8560   IS          iscoltmp;
8561   PetscBool   flg;
8562 
8563   PetscFunctionBegin;
8564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8565   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8566   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8567   PetscAssertPointer(newmat, 5);
8568   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8569   PetscValidType(mat, 1);
8570   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8571   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8572 
8573   MatCheckPreallocated(mat, 1);
8574   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8575 
8576   if (!iscol || isrow == iscol) {
8577     PetscBool   stride;
8578     PetscMPIInt grabentirematrix = 0, grab;
8579     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8580     if (stride) {
8581       PetscInt first, step, n, rstart, rend;
8582       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8583       if (step == 1) {
8584         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8585         if (rstart == first) {
8586           PetscCall(ISGetLocalSize(isrow, &n));
8587           if (n == rend - rstart) grabentirematrix = 1;
8588         }
8589       }
8590     }
8591     PetscCallMPI(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8592     if (grab) {
8593       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8594       if (cll == MAT_INITIAL_MATRIX) {
8595         *newmat = mat;
8596         PetscCall(PetscObjectReference((PetscObject)mat));
8597       }
8598       PetscFunctionReturn(PETSC_SUCCESS);
8599     }
8600   }
8601 
8602   if (!iscol) {
8603     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8604   } else {
8605     iscoltmp = iscol;
8606   }
8607 
8608   /* if original matrix is on just one processor then use submatrix generated */
8609   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8610     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8611     goto setproperties;
8612   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8613     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8614     *newmat = *local;
8615     PetscCall(PetscFree(local));
8616     goto setproperties;
8617   } else if (!mat->ops->createsubmatrix) {
8618     /* Create a new matrix type that implements the operation using the full matrix */
8619     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8620     switch (cll) {
8621     case MAT_INITIAL_MATRIX:
8622       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8623       break;
8624     case MAT_REUSE_MATRIX:
8625       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8626       break;
8627     default:
8628       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8629     }
8630     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8631     goto setproperties;
8632   }
8633 
8634   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8635   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8636   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8637 
8638 setproperties:
8639   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8640     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8641     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8642   }
8643   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8644   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8645   PetscFunctionReturn(PETSC_SUCCESS);
8646 }
8647 
8648 /*@
8649   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8650 
8651   Not Collective
8652 
8653   Input Parameters:
8654 + A - the matrix we wish to propagate options from
8655 - B - the matrix we wish to propagate options to
8656 
8657   Level: beginner
8658 
8659   Note:
8660   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8661 
8662 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8663 @*/
8664 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8665 {
8666   PetscFunctionBegin;
8667   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8668   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8669   B->symmetry_eternal            = A->symmetry_eternal;
8670   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8671   B->symmetric                   = A->symmetric;
8672   B->structurally_symmetric      = A->structurally_symmetric;
8673   B->spd                         = A->spd;
8674   B->hermitian                   = A->hermitian;
8675   PetscFunctionReturn(PETSC_SUCCESS);
8676 }
8677 
8678 /*@
8679   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8680   used during the assembly process to store values that belong to
8681   other processors.
8682 
8683   Not Collective
8684 
8685   Input Parameters:
8686 + mat   - the matrix
8687 . size  - the initial size of the stash.
8688 - bsize - the initial size of the block-stash(if used).
8689 
8690   Options Database Keys:
8691 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8692 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8693 
8694   Level: intermediate
8695 
8696   Notes:
8697   The block-stash is used for values set with `MatSetValuesBlocked()` while
8698   the stash is used for values set with `MatSetValues()`
8699 
8700   Run with the option -info and look for output of the form
8701   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8702   to determine the appropriate value, MM, to use for size and
8703   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8704   to determine the value, BMM to use for bsize
8705 
8706 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8707 @*/
8708 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8709 {
8710   PetscFunctionBegin;
8711   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8712   PetscValidType(mat, 1);
8713   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8714   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8715   PetscFunctionReturn(PETSC_SUCCESS);
8716 }
8717 
8718 /*@
8719   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8720   the matrix
8721 
8722   Neighbor-wise Collective
8723 
8724   Input Parameters:
8725 + A - the matrix
8726 . x - the vector to be multiplied by the interpolation operator
8727 - y - the vector to be added to the result
8728 
8729   Output Parameter:
8730 . w - the resulting vector
8731 
8732   Level: intermediate
8733 
8734   Notes:
8735   `w` may be the same vector as `y`.
8736 
8737   This allows one to use either the restriction or interpolation (its transpose)
8738   matrix to do the interpolation
8739 
8740 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8741 @*/
8742 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8743 {
8744   PetscInt M, N, Ny;
8745 
8746   PetscFunctionBegin;
8747   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8748   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8749   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8750   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8751   PetscCall(MatGetSize(A, &M, &N));
8752   PetscCall(VecGetSize(y, &Ny));
8753   if (M == Ny) {
8754     PetscCall(MatMultAdd(A, x, y, w));
8755   } else {
8756     PetscCall(MatMultTransposeAdd(A, x, y, w));
8757   }
8758   PetscFunctionReturn(PETSC_SUCCESS);
8759 }
8760 
8761 /*@
8762   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8763   the matrix
8764 
8765   Neighbor-wise Collective
8766 
8767   Input Parameters:
8768 + A - the matrix
8769 - x - the vector to be interpolated
8770 
8771   Output Parameter:
8772 . y - the resulting vector
8773 
8774   Level: intermediate
8775 
8776   Note:
8777   This allows one to use either the restriction or interpolation (its transpose)
8778   matrix to do the interpolation
8779 
8780 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8781 @*/
8782 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8783 {
8784   PetscInt M, N, Ny;
8785 
8786   PetscFunctionBegin;
8787   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8788   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8789   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8790   PetscCall(MatGetSize(A, &M, &N));
8791   PetscCall(VecGetSize(y, &Ny));
8792   if (M == Ny) {
8793     PetscCall(MatMult(A, x, y));
8794   } else {
8795     PetscCall(MatMultTranspose(A, x, y));
8796   }
8797   PetscFunctionReturn(PETSC_SUCCESS);
8798 }
8799 
8800 /*@
8801   MatRestrict - $y = A*x$ or $A^T*x$
8802 
8803   Neighbor-wise Collective
8804 
8805   Input Parameters:
8806 + A - the matrix
8807 - x - the vector to be restricted
8808 
8809   Output Parameter:
8810 . y - the resulting vector
8811 
8812   Level: intermediate
8813 
8814   Note:
8815   This allows one to use either the restriction or interpolation (its transpose)
8816   matrix to do the restriction
8817 
8818 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8819 @*/
8820 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8821 {
8822   PetscInt M, N, Nx;
8823 
8824   PetscFunctionBegin;
8825   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8826   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8827   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8828   PetscCall(MatGetSize(A, &M, &N));
8829   PetscCall(VecGetSize(x, &Nx));
8830   if (M == Nx) {
8831     PetscCall(MatMultTranspose(A, x, y));
8832   } else {
8833     PetscCall(MatMult(A, x, y));
8834   }
8835   PetscFunctionReturn(PETSC_SUCCESS);
8836 }
8837 
8838 /*@
8839   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8840 
8841   Neighbor-wise Collective
8842 
8843   Input Parameters:
8844 + A - the matrix
8845 . x - the input dense matrix to be multiplied
8846 - w - the input dense matrix to be added to the result
8847 
8848   Output Parameter:
8849 . y - the output dense matrix
8850 
8851   Level: intermediate
8852 
8853   Note:
8854   This allows one to use either the restriction or interpolation (its transpose)
8855   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8856   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8857 
8858 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8859 @*/
8860 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8861 {
8862   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8863   PetscBool trans = PETSC_TRUE;
8864   MatReuse  reuse = MAT_INITIAL_MATRIX;
8865 
8866   PetscFunctionBegin;
8867   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8868   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8869   PetscValidType(x, 2);
8870   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8871   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8872   PetscCall(MatGetSize(A, &M, &N));
8873   PetscCall(MatGetSize(x, &Mx, &Nx));
8874   if (N == Mx) trans = PETSC_FALSE;
8875   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);
8876   Mo = trans ? N : M;
8877   if (*y) {
8878     PetscCall(MatGetSize(*y, &My, &Ny));
8879     if (Mo == My && Nx == Ny) {
8880       reuse = MAT_REUSE_MATRIX;
8881     } else {
8882       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);
8883       PetscCall(MatDestroy(y));
8884     }
8885   }
8886 
8887   if (w && *y == w) { /* this is to minimize changes in PCMG */
8888     PetscBool flg;
8889 
8890     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8891     if (w) {
8892       PetscInt My, Ny, Mw, Nw;
8893 
8894       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8895       PetscCall(MatGetSize(*y, &My, &Ny));
8896       PetscCall(MatGetSize(w, &Mw, &Nw));
8897       if (!flg || My != Mw || Ny != Nw) w = NULL;
8898     }
8899     if (!w) {
8900       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8901       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8902       PetscCall(PetscObjectDereference((PetscObject)w));
8903     } else {
8904       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8905     }
8906   }
8907   if (!trans) {
8908     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8909   } else {
8910     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8911   }
8912   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8913   PetscFunctionReturn(PETSC_SUCCESS);
8914 }
8915 
8916 /*@
8917   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8918 
8919   Neighbor-wise Collective
8920 
8921   Input Parameters:
8922 + A - the matrix
8923 - x - the input dense matrix
8924 
8925   Output Parameter:
8926 . y - the output dense matrix
8927 
8928   Level: intermediate
8929 
8930   Note:
8931   This allows one to use either the restriction or interpolation (its transpose)
8932   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8933   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8934 
8935 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8936 @*/
8937 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8938 {
8939   PetscFunctionBegin;
8940   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8941   PetscFunctionReturn(PETSC_SUCCESS);
8942 }
8943 
8944 /*@
8945   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8946 
8947   Neighbor-wise Collective
8948 
8949   Input Parameters:
8950 + A - the matrix
8951 - x - the input dense matrix
8952 
8953   Output Parameter:
8954 . y - the output dense matrix
8955 
8956   Level: intermediate
8957 
8958   Note:
8959   This allows one to use either the restriction or interpolation (its transpose)
8960   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8961   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8962 
8963 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8964 @*/
8965 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8966 {
8967   PetscFunctionBegin;
8968   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8969   PetscFunctionReturn(PETSC_SUCCESS);
8970 }
8971 
8972 /*@
8973   MatGetNullSpace - retrieves the null space of a matrix.
8974 
8975   Logically Collective
8976 
8977   Input Parameters:
8978 + mat    - the matrix
8979 - nullsp - the null space object
8980 
8981   Level: developer
8982 
8983 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8984 @*/
8985 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8986 {
8987   PetscFunctionBegin;
8988   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8989   PetscAssertPointer(nullsp, 2);
8990   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8991   PetscFunctionReturn(PETSC_SUCCESS);
8992 }
8993 
8994 /*@C
8995   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
8996 
8997   Logically Collective
8998 
8999   Input Parameters:
9000 + n   - the number of matrices
9001 - mat - the array of matrices
9002 
9003   Output Parameters:
9004 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
9005 
9006   Level: developer
9007 
9008   Note:
9009   Call `MatRestoreNullspaces()` to provide these to another array of matrices
9010 
9011 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9012           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
9013 @*/
9014 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9015 {
9016   PetscFunctionBegin;
9017   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9018   PetscAssertPointer(mat, 2);
9019   PetscAssertPointer(nullsp, 3);
9020 
9021   PetscCall(PetscCalloc1(3 * n, nullsp));
9022   for (PetscInt i = 0; i < n; i++) {
9023     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9024     (*nullsp)[i] = mat[i]->nullsp;
9025     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
9026     (*nullsp)[n + i] = mat[i]->nearnullsp;
9027     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
9028     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
9029     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
9030   }
9031   PetscFunctionReturn(PETSC_SUCCESS);
9032 }
9033 
9034 /*@C
9035   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
9036 
9037   Logically Collective
9038 
9039   Input Parameters:
9040 + n      - the number of matrices
9041 . mat    - the array of matrices
9042 - nullsp - an array of null spaces
9043 
9044   Level: developer
9045 
9046   Note:
9047   Call `MatGetNullSpaces()` to create `nullsp`
9048 
9049 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9050           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9051 @*/
9052 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9053 {
9054   PetscFunctionBegin;
9055   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9056   PetscAssertPointer(mat, 2);
9057   PetscAssertPointer(nullsp, 3);
9058   PetscAssertPointer(*nullsp, 3);
9059 
9060   for (PetscInt i = 0; i < n; i++) {
9061     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9062     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9063     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9064     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9065     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9066     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9067     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9068   }
9069   PetscCall(PetscFree(*nullsp));
9070   PetscFunctionReturn(PETSC_SUCCESS);
9071 }
9072 
9073 /*@
9074   MatSetNullSpace - attaches a null space to a matrix.
9075 
9076   Logically Collective
9077 
9078   Input Parameters:
9079 + mat    - the matrix
9080 - nullsp - the null space object
9081 
9082   Level: advanced
9083 
9084   Notes:
9085   This null space is used by the `KSP` linear solvers to solve singular systems.
9086 
9087   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`
9088 
9089   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
9090   to zero but the linear system will still be solved in a least squares sense.
9091 
9092   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9093   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)$.
9094   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
9095   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
9096   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$).
9097   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9098 
9099   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9100   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9101   routine also automatically calls `MatSetTransposeNullSpace()`.
9102 
9103   The user should call `MatNullSpaceDestroy()`.
9104 
9105 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9106           `KSPSetPCSide()`
9107 @*/
9108 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9109 {
9110   PetscFunctionBegin;
9111   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9112   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9113   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9114   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9115   mat->nullsp = nullsp;
9116   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9117   PetscFunctionReturn(PETSC_SUCCESS);
9118 }
9119 
9120 /*@
9121   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9122 
9123   Logically Collective
9124 
9125   Input Parameters:
9126 + mat    - the matrix
9127 - nullsp - the null space object
9128 
9129   Level: developer
9130 
9131 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9132 @*/
9133 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9134 {
9135   PetscFunctionBegin;
9136   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9137   PetscValidType(mat, 1);
9138   PetscAssertPointer(nullsp, 2);
9139   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9140   PetscFunctionReturn(PETSC_SUCCESS);
9141 }
9142 
9143 /*@
9144   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9145 
9146   Logically Collective
9147 
9148   Input Parameters:
9149 + mat    - the matrix
9150 - nullsp - the null space object
9151 
9152   Level: advanced
9153 
9154   Notes:
9155   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9156 
9157   See `MatSetNullSpace()`
9158 
9159 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9160 @*/
9161 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9162 {
9163   PetscFunctionBegin;
9164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9165   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9166   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9167   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9168   mat->transnullsp = nullsp;
9169   PetscFunctionReturn(PETSC_SUCCESS);
9170 }
9171 
9172 /*@
9173   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9174   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9175 
9176   Logically Collective
9177 
9178   Input Parameters:
9179 + mat    - the matrix
9180 - nullsp - the null space object
9181 
9182   Level: advanced
9183 
9184   Notes:
9185   Overwrites any previous near null space that may have been attached
9186 
9187   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9188 
9189 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9190 @*/
9191 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9192 {
9193   PetscFunctionBegin;
9194   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9195   PetscValidType(mat, 1);
9196   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9197   MatCheckPreallocated(mat, 1);
9198   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9199   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9200   mat->nearnullsp = nullsp;
9201   PetscFunctionReturn(PETSC_SUCCESS);
9202 }
9203 
9204 /*@
9205   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9206 
9207   Not Collective
9208 
9209   Input Parameter:
9210 . mat - the matrix
9211 
9212   Output Parameter:
9213 . nullsp - the null space object, `NULL` if not set
9214 
9215   Level: advanced
9216 
9217 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9218 @*/
9219 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9220 {
9221   PetscFunctionBegin;
9222   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9223   PetscValidType(mat, 1);
9224   PetscAssertPointer(nullsp, 2);
9225   MatCheckPreallocated(mat, 1);
9226   *nullsp = mat->nearnullsp;
9227   PetscFunctionReturn(PETSC_SUCCESS);
9228 }
9229 
9230 /*@
9231   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9232 
9233   Collective
9234 
9235   Input Parameters:
9236 + mat  - the matrix
9237 . row  - row/column permutation
9238 - info - information on desired factorization process
9239 
9240   Level: developer
9241 
9242   Notes:
9243   Probably really in-place only when level of fill is zero, otherwise allocates
9244   new space to store factored matrix and deletes previous memory.
9245 
9246   Most users should employ the `KSP` interface for linear solvers
9247   instead of working directly with matrix algebra routines such as this.
9248   See, e.g., `KSPCreate()`.
9249 
9250   Developer Note:
9251   The Fortran interface is not autogenerated as the
9252   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9253 
9254 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9255 @*/
9256 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9257 {
9258   PetscFunctionBegin;
9259   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9260   PetscValidType(mat, 1);
9261   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9262   PetscAssertPointer(info, 3);
9263   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9264   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9265   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9266   MatCheckPreallocated(mat, 1);
9267   PetscUseTypeMethod(mat, iccfactor, row, info);
9268   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9269   PetscFunctionReturn(PETSC_SUCCESS);
9270 }
9271 
9272 /*@
9273   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9274   ghosted ones.
9275 
9276   Not Collective
9277 
9278   Input Parameters:
9279 + mat  - the matrix
9280 - diag - the diagonal values, including ghost ones
9281 
9282   Level: developer
9283 
9284   Notes:
9285   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9286 
9287   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9288 
9289 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9290 @*/
9291 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9292 {
9293   PetscMPIInt size;
9294 
9295   PetscFunctionBegin;
9296   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9297   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9298   PetscValidType(mat, 1);
9299 
9300   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9301   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9302   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9303   if (size == 1) {
9304     PetscInt n, m;
9305     PetscCall(VecGetSize(diag, &n));
9306     PetscCall(MatGetSize(mat, NULL, &m));
9307     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9308     PetscCall(MatDiagonalScale(mat, NULL, diag));
9309   } else {
9310     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9311   }
9312   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9313   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9314   PetscFunctionReturn(PETSC_SUCCESS);
9315 }
9316 
9317 /*@
9318   MatGetInertia - Gets the inertia from a factored matrix
9319 
9320   Collective
9321 
9322   Input Parameter:
9323 . mat - the matrix
9324 
9325   Output Parameters:
9326 + nneg  - number of negative eigenvalues
9327 . nzero - number of zero eigenvalues
9328 - npos  - number of positive eigenvalues
9329 
9330   Level: advanced
9331 
9332   Note:
9333   Matrix must have been factored by `MatCholeskyFactor()`
9334 
9335 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9336 @*/
9337 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9338 {
9339   PetscFunctionBegin;
9340   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9341   PetscValidType(mat, 1);
9342   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9343   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9344   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9345   PetscFunctionReturn(PETSC_SUCCESS);
9346 }
9347 
9348 /*@C
9349   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9350 
9351   Neighbor-wise Collective
9352 
9353   Input Parameters:
9354 + mat - the factored matrix obtained with `MatGetFactor()`
9355 - b   - the right-hand-side vectors
9356 
9357   Output Parameter:
9358 . x - the result vectors
9359 
9360   Level: developer
9361 
9362   Note:
9363   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9364   call `MatSolves`(A,x,x).
9365 
9366 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9367 @*/
9368 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9369 {
9370   PetscFunctionBegin;
9371   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9372   PetscValidType(mat, 1);
9373   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9374   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9375   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9376 
9377   MatCheckPreallocated(mat, 1);
9378   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9379   PetscUseTypeMethod(mat, solves, b, x);
9380   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9381   PetscFunctionReturn(PETSC_SUCCESS);
9382 }
9383 
9384 /*@
9385   MatIsSymmetric - Test whether a matrix is symmetric
9386 
9387   Collective
9388 
9389   Input Parameters:
9390 + A   - the matrix to test
9391 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9392 
9393   Output Parameter:
9394 . flg - the result
9395 
9396   Level: intermediate
9397 
9398   Notes:
9399   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9400 
9401   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9402 
9403   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9404   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9405 
9406 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9407           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9408 @*/
9409 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9410 {
9411   PetscFunctionBegin;
9412   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9413   PetscAssertPointer(flg, 3);
9414   if (A->symmetric != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->symmetric);
9415   else {
9416     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9417     else PetscCall(MatIsTranspose(A, A, tol, flg));
9418     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9419   }
9420   PetscFunctionReturn(PETSC_SUCCESS);
9421 }
9422 
9423 /*@
9424   MatIsHermitian - Test whether a matrix is Hermitian
9425 
9426   Collective
9427 
9428   Input Parameters:
9429 + A   - the matrix to test
9430 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9431 
9432   Output Parameter:
9433 . flg - the result
9434 
9435   Level: intermediate
9436 
9437   Notes:
9438   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9439 
9440   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9441 
9442   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9443   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9444 
9445 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9446           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9447 @*/
9448 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9449 {
9450   PetscFunctionBegin;
9451   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9452   PetscAssertPointer(flg, 3);
9453   if (A->hermitian != PETSC_BOOL3_UNKNOWN && !tol) *flg = PetscBool3ToBool(A->hermitian);
9454   else {
9455     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9456     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9457     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9458   }
9459   PetscFunctionReturn(PETSC_SUCCESS);
9460 }
9461 
9462 /*@
9463   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9464 
9465   Not Collective
9466 
9467   Input Parameter:
9468 . A - the matrix to check
9469 
9470   Output Parameters:
9471 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9472 - flg - the result (only valid if set is `PETSC_TRUE`)
9473 
9474   Level: advanced
9475 
9476   Notes:
9477   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9478   if you want it explicitly checked
9479 
9480   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9481   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9482 
9483 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9484 @*/
9485 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9486 {
9487   PetscFunctionBegin;
9488   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9489   PetscAssertPointer(set, 2);
9490   PetscAssertPointer(flg, 3);
9491   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9492     *set = PETSC_TRUE;
9493     *flg = PetscBool3ToBool(A->symmetric);
9494   } else {
9495     *set = PETSC_FALSE;
9496   }
9497   PetscFunctionReturn(PETSC_SUCCESS);
9498 }
9499 
9500 /*@
9501   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9502 
9503   Not Collective
9504 
9505   Input Parameter:
9506 . A - the matrix to check
9507 
9508   Output Parameters:
9509 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9510 - flg - the result (only valid if set is `PETSC_TRUE`)
9511 
9512   Level: advanced
9513 
9514   Notes:
9515   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9516 
9517   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9518   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9519 
9520 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9521 @*/
9522 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9523 {
9524   PetscFunctionBegin;
9525   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9526   PetscAssertPointer(set, 2);
9527   PetscAssertPointer(flg, 3);
9528   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9529     *set = PETSC_TRUE;
9530     *flg = PetscBool3ToBool(A->spd);
9531   } else {
9532     *set = PETSC_FALSE;
9533   }
9534   PetscFunctionReturn(PETSC_SUCCESS);
9535 }
9536 
9537 /*@
9538   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9539 
9540   Not Collective
9541 
9542   Input Parameter:
9543 . A - the matrix to check
9544 
9545   Output Parameters:
9546 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9547 - flg - the result (only valid if set is `PETSC_TRUE`)
9548 
9549   Level: advanced
9550 
9551   Notes:
9552   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9553   if you want it explicitly checked
9554 
9555   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9556   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9557 
9558 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9559 @*/
9560 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9561 {
9562   PetscFunctionBegin;
9563   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9564   PetscAssertPointer(set, 2);
9565   PetscAssertPointer(flg, 3);
9566   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9567     *set = PETSC_TRUE;
9568     *flg = PetscBool3ToBool(A->hermitian);
9569   } else {
9570     *set = PETSC_FALSE;
9571   }
9572   PetscFunctionReturn(PETSC_SUCCESS);
9573 }
9574 
9575 /*@
9576   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9577 
9578   Collective
9579 
9580   Input Parameter:
9581 . A - the matrix to test
9582 
9583   Output Parameter:
9584 . flg - the result
9585 
9586   Level: intermediate
9587 
9588   Notes:
9589   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9590 
9591   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
9592   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9593 
9594 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9595 @*/
9596 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9597 {
9598   PetscFunctionBegin;
9599   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9600   PetscAssertPointer(flg, 2);
9601   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9602     *flg = PetscBool3ToBool(A->structurally_symmetric);
9603   } else {
9604     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9605     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9606   }
9607   PetscFunctionReturn(PETSC_SUCCESS);
9608 }
9609 
9610 /*@
9611   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9612 
9613   Not Collective
9614 
9615   Input Parameter:
9616 . A - the matrix to check
9617 
9618   Output Parameters:
9619 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9620 - flg - the result (only valid if set is PETSC_TRUE)
9621 
9622   Level: advanced
9623 
9624   Notes:
9625   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
9626   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9627 
9628   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9629 
9630 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9631 @*/
9632 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9633 {
9634   PetscFunctionBegin;
9635   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9636   PetscAssertPointer(set, 2);
9637   PetscAssertPointer(flg, 3);
9638   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9639     *set = PETSC_TRUE;
9640     *flg = PetscBool3ToBool(A->structurally_symmetric);
9641   } else {
9642     *set = PETSC_FALSE;
9643   }
9644   PetscFunctionReturn(PETSC_SUCCESS);
9645 }
9646 
9647 /*@
9648   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9649   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9650 
9651   Not Collective
9652 
9653   Input Parameter:
9654 . mat - the matrix
9655 
9656   Output Parameters:
9657 + nstash    - the size of the stash
9658 . reallocs  - the number of additional mallocs incurred.
9659 . bnstash   - the size of the block stash
9660 - breallocs - the number of additional mallocs incurred.in the block stash
9661 
9662   Level: advanced
9663 
9664 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9665 @*/
9666 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9667 {
9668   PetscFunctionBegin;
9669   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9670   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9671   PetscFunctionReturn(PETSC_SUCCESS);
9672 }
9673 
9674 /*@
9675   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9676   parallel layout, `PetscLayout` for rows and columns
9677 
9678   Collective
9679 
9680   Input Parameter:
9681 . mat - the matrix
9682 
9683   Output Parameters:
9684 + right - (optional) vector that the matrix can be multiplied against
9685 - left  - (optional) vector that the matrix vector product can be stored in
9686 
9687   Level: advanced
9688 
9689   Notes:
9690   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()`.
9691 
9692   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9693 
9694 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9695 @*/
9696 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9697 {
9698   PetscFunctionBegin;
9699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9700   PetscValidType(mat, 1);
9701   if (mat->ops->getvecs) {
9702     PetscUseTypeMethod(mat, getvecs, right, left);
9703   } else {
9704     if (right) {
9705       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9706       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9707       PetscCall(VecSetType(*right, mat->defaultvectype));
9708 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9709       if (mat->boundtocpu && mat->bindingpropagates) {
9710         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9711         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9712       }
9713 #endif
9714     }
9715     if (left) {
9716       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9717       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9718       PetscCall(VecSetType(*left, mat->defaultvectype));
9719 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9720       if (mat->boundtocpu && mat->bindingpropagates) {
9721         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9722         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9723       }
9724 #endif
9725     }
9726   }
9727   PetscFunctionReturn(PETSC_SUCCESS);
9728 }
9729 
9730 /*@
9731   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9732   with default values.
9733 
9734   Not Collective
9735 
9736   Input Parameter:
9737 . info - the `MatFactorInfo` data structure
9738 
9739   Level: developer
9740 
9741   Notes:
9742   The solvers are generally used through the `KSP` and `PC` objects, for example
9743   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9744 
9745   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9746 
9747 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9748 @*/
9749 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9750 {
9751   PetscFunctionBegin;
9752   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9753   PetscFunctionReturn(PETSC_SUCCESS);
9754 }
9755 
9756 /*@
9757   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9758 
9759   Collective
9760 
9761   Input Parameters:
9762 + mat - the factored matrix
9763 - is  - the index set defining the Schur indices (0-based)
9764 
9765   Level: advanced
9766 
9767   Notes:
9768   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9769 
9770   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9771 
9772   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9773 
9774 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9775           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9776 @*/
9777 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9778 {
9779   PetscErrorCode (*f)(Mat, IS);
9780 
9781   PetscFunctionBegin;
9782   PetscValidType(mat, 1);
9783   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9784   PetscValidType(is, 2);
9785   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9786   PetscCheckSameComm(mat, 1, is, 2);
9787   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9788   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9789   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9790   PetscCall(MatDestroy(&mat->schur));
9791   PetscCall((*f)(mat, is));
9792   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9793   PetscFunctionReturn(PETSC_SUCCESS);
9794 }
9795 
9796 /*@
9797   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9798 
9799   Logically Collective
9800 
9801   Input Parameters:
9802 + F      - the factored matrix obtained by calling `MatGetFactor()`
9803 . S      - location where to return the Schur complement, can be `NULL`
9804 - status - the status of the Schur complement matrix, can be `NULL`
9805 
9806   Level: advanced
9807 
9808   Notes:
9809   You must call `MatFactorSetSchurIS()` before calling this routine.
9810 
9811   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9812 
9813   The routine provides a copy of the Schur matrix stored within the solver data structures.
9814   The caller must destroy the object when it is no longer needed.
9815   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9816 
9817   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)
9818 
9819   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9820 
9821   Developer Note:
9822   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9823   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9824 
9825 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9826 @*/
9827 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9828 {
9829   PetscFunctionBegin;
9830   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9831   if (S) PetscAssertPointer(S, 2);
9832   if (status) PetscAssertPointer(status, 3);
9833   if (S) {
9834     PetscErrorCode (*f)(Mat, Mat *);
9835 
9836     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9837     if (f) {
9838       PetscCall((*f)(F, S));
9839     } else {
9840       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9841     }
9842   }
9843   if (status) *status = F->schur_status;
9844   PetscFunctionReturn(PETSC_SUCCESS);
9845 }
9846 
9847 /*@
9848   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9849 
9850   Logically Collective
9851 
9852   Input Parameters:
9853 + F      - the factored matrix obtained by calling `MatGetFactor()`
9854 . S      - location where to return the Schur complement, can be `NULL`
9855 - status - the status of the Schur complement matrix, can be `NULL`
9856 
9857   Level: advanced
9858 
9859   Notes:
9860   You must call `MatFactorSetSchurIS()` before calling this routine.
9861 
9862   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9863 
9864   The routine returns a the Schur Complement stored within the data structures of the solver.
9865 
9866   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9867 
9868   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9869 
9870   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9871 
9872   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9873 
9874 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9875 @*/
9876 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9877 {
9878   PetscFunctionBegin;
9879   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9880   if (S) {
9881     PetscAssertPointer(S, 2);
9882     *S = F->schur;
9883   }
9884   if (status) {
9885     PetscAssertPointer(status, 3);
9886     *status = F->schur_status;
9887   }
9888   PetscFunctionReturn(PETSC_SUCCESS);
9889 }
9890 
9891 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9892 {
9893   Mat S = F->schur;
9894 
9895   PetscFunctionBegin;
9896   switch (F->schur_status) {
9897   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9898   case MAT_FACTOR_SCHUR_INVERTED:
9899     if (S) {
9900       S->ops->solve             = NULL;
9901       S->ops->matsolve          = NULL;
9902       S->ops->solvetranspose    = NULL;
9903       S->ops->matsolvetranspose = NULL;
9904       S->ops->solveadd          = NULL;
9905       S->ops->solvetransposeadd = NULL;
9906       S->factortype             = MAT_FACTOR_NONE;
9907       PetscCall(PetscFree(S->solvertype));
9908     }
9909   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9910     break;
9911   default:
9912     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9913   }
9914   PetscFunctionReturn(PETSC_SUCCESS);
9915 }
9916 
9917 /*@
9918   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9919 
9920   Logically Collective
9921 
9922   Input Parameters:
9923 + F      - the factored matrix obtained by calling `MatGetFactor()`
9924 . S      - location where the Schur complement is stored
9925 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9926 
9927   Level: advanced
9928 
9929 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9930 @*/
9931 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9932 {
9933   PetscFunctionBegin;
9934   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9935   if (S) {
9936     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9937     *S = NULL;
9938   }
9939   F->schur_status = status;
9940   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9941   PetscFunctionReturn(PETSC_SUCCESS);
9942 }
9943 
9944 /*@
9945   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9946 
9947   Logically Collective
9948 
9949   Input Parameters:
9950 + F   - the factored matrix obtained by calling `MatGetFactor()`
9951 . rhs - location where the right-hand side of the Schur complement system is stored
9952 - sol - location where the solution of the Schur complement system has to be returned
9953 
9954   Level: advanced
9955 
9956   Notes:
9957   The sizes of the vectors should match the size of the Schur complement
9958 
9959   Must be called after `MatFactorSetSchurIS()`
9960 
9961 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9962 @*/
9963 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9964 {
9965   PetscFunctionBegin;
9966   PetscValidType(F, 1);
9967   PetscValidType(rhs, 2);
9968   PetscValidType(sol, 3);
9969   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9970   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9971   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9972   PetscCheckSameComm(F, 1, rhs, 2);
9973   PetscCheckSameComm(F, 1, sol, 3);
9974   PetscCall(MatFactorFactorizeSchurComplement(F));
9975   switch (F->schur_status) {
9976   case MAT_FACTOR_SCHUR_FACTORED:
9977     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9978     break;
9979   case MAT_FACTOR_SCHUR_INVERTED:
9980     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9981     break;
9982   default:
9983     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9984   }
9985   PetscFunctionReturn(PETSC_SUCCESS);
9986 }
9987 
9988 /*@
9989   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9990 
9991   Logically Collective
9992 
9993   Input Parameters:
9994 + F   - the factored matrix obtained by calling `MatGetFactor()`
9995 . rhs - location where the right-hand side of the Schur complement system is stored
9996 - sol - location where the solution of the Schur complement system has to be returned
9997 
9998   Level: advanced
9999 
10000   Notes:
10001   The sizes of the vectors should match the size of the Schur complement
10002 
10003   Must be called after `MatFactorSetSchurIS()`
10004 
10005 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
10006 @*/
10007 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
10008 {
10009   PetscFunctionBegin;
10010   PetscValidType(F, 1);
10011   PetscValidType(rhs, 2);
10012   PetscValidType(sol, 3);
10013   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10014   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
10015   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10016   PetscCheckSameComm(F, 1, rhs, 2);
10017   PetscCheckSameComm(F, 1, sol, 3);
10018   PetscCall(MatFactorFactorizeSchurComplement(F));
10019   switch (F->schur_status) {
10020   case MAT_FACTOR_SCHUR_FACTORED:
10021     PetscCall(MatSolve(F->schur, rhs, sol));
10022     break;
10023   case MAT_FACTOR_SCHUR_INVERTED:
10024     PetscCall(MatMult(F->schur, rhs, sol));
10025     break;
10026   default:
10027     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10028   }
10029   PetscFunctionReturn(PETSC_SUCCESS);
10030 }
10031 
10032 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
10033 #if PetscDefined(HAVE_CUDA)
10034 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
10035 #endif
10036 
10037 /* Schur status updated in the interface */
10038 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
10039 {
10040   Mat S = F->schur;
10041 
10042   PetscFunctionBegin;
10043   if (S) {
10044     PetscMPIInt size;
10045     PetscBool   isdense, isdensecuda;
10046 
10047     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10048     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10049     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10050     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10051     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10052     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10053     if (isdense) {
10054       PetscCall(MatSeqDenseInvertFactors_Private(S));
10055     } else if (isdensecuda) {
10056 #if defined(PETSC_HAVE_CUDA)
10057       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10058 #endif
10059     }
10060     // HIP??????????????
10061     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10062   }
10063   PetscFunctionReturn(PETSC_SUCCESS);
10064 }
10065 
10066 /*@
10067   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10068 
10069   Logically Collective
10070 
10071   Input Parameter:
10072 . F - the factored matrix obtained by calling `MatGetFactor()`
10073 
10074   Level: advanced
10075 
10076   Notes:
10077   Must be called after `MatFactorSetSchurIS()`.
10078 
10079   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10080 
10081 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10082 @*/
10083 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10084 {
10085   PetscFunctionBegin;
10086   PetscValidType(F, 1);
10087   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10088   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10089   PetscCall(MatFactorFactorizeSchurComplement(F));
10090   PetscCall(MatFactorInvertSchurComplement_Private(F));
10091   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10092   PetscFunctionReturn(PETSC_SUCCESS);
10093 }
10094 
10095 /*@
10096   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10097 
10098   Logically Collective
10099 
10100   Input Parameter:
10101 . F - the factored matrix obtained by calling `MatGetFactor()`
10102 
10103   Level: advanced
10104 
10105   Note:
10106   Must be called after `MatFactorSetSchurIS()`
10107 
10108 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10109 @*/
10110 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10111 {
10112   MatFactorInfo info;
10113 
10114   PetscFunctionBegin;
10115   PetscValidType(F, 1);
10116   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10117   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10118   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10119   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10120   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10121     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10122   } else {
10123     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10124   }
10125   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10126   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10127   PetscFunctionReturn(PETSC_SUCCESS);
10128 }
10129 
10130 /*@
10131   MatPtAP - Creates the matrix product $C = P^T * A * P$
10132 
10133   Neighbor-wise Collective
10134 
10135   Input Parameters:
10136 + A     - the matrix
10137 . P     - the projection matrix
10138 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10139 - 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
10140           if the result is a dense matrix this is irrelevant
10141 
10142   Output Parameter:
10143 . C - the product matrix
10144 
10145   Level: intermediate
10146 
10147   Notes:
10148   C will be created and must be destroyed by the user with `MatDestroy()`.
10149 
10150   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10151 
10152   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10153 
10154   Developer Note:
10155   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10156 
10157 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10158 @*/
10159 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10160 {
10161   PetscFunctionBegin;
10162   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10163   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10164 
10165   if (scall == MAT_INITIAL_MATRIX) {
10166     PetscCall(MatProductCreate(A, P, NULL, C));
10167     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10168     PetscCall(MatProductSetAlgorithm(*C, "default"));
10169     PetscCall(MatProductSetFill(*C, fill));
10170 
10171     (*C)->product->api_user = PETSC_TRUE;
10172     PetscCall(MatProductSetFromOptions(*C));
10173     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);
10174     PetscCall(MatProductSymbolic(*C));
10175   } else { /* scall == MAT_REUSE_MATRIX */
10176     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10177   }
10178 
10179   PetscCall(MatProductNumeric(*C));
10180   (*C)->symmetric = A->symmetric;
10181   (*C)->spd       = A->spd;
10182   PetscFunctionReturn(PETSC_SUCCESS);
10183 }
10184 
10185 /*@
10186   MatRARt - Creates the matrix product $C = R * A * R^T$
10187 
10188   Neighbor-wise Collective
10189 
10190   Input Parameters:
10191 + A     - the matrix
10192 . R     - the projection matrix
10193 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10194 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10195           if the result is a dense matrix this is irrelevant
10196 
10197   Output Parameter:
10198 . C - the product matrix
10199 
10200   Level: intermediate
10201 
10202   Notes:
10203   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10204 
10205   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10206 
10207   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10208   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10209   the parallel `MatRARt()` is implemented computing the explicit transpose of `R`, which can be very expensive.
10210   We recommend using `MatPtAP()` when possible.
10211 
10212   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10213 
10214 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10215 @*/
10216 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10217 {
10218   PetscFunctionBegin;
10219   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10220   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10221 
10222   if (scall == MAT_INITIAL_MATRIX) {
10223     PetscCall(MatProductCreate(A, R, NULL, C));
10224     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10225     PetscCall(MatProductSetAlgorithm(*C, "default"));
10226     PetscCall(MatProductSetFill(*C, fill));
10227 
10228     (*C)->product->api_user = PETSC_TRUE;
10229     PetscCall(MatProductSetFromOptions(*C));
10230     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);
10231     PetscCall(MatProductSymbolic(*C));
10232   } else { /* scall == MAT_REUSE_MATRIX */
10233     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10234   }
10235 
10236   PetscCall(MatProductNumeric(*C));
10237   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10238   PetscFunctionReturn(PETSC_SUCCESS);
10239 }
10240 
10241 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10242 {
10243   PetscBool flg = PETSC_TRUE;
10244 
10245   PetscFunctionBegin;
10246   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10247   if (scall == MAT_INITIAL_MATRIX) {
10248     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10249     PetscCall(MatProductCreate(A, B, NULL, C));
10250     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10251     PetscCall(MatProductSetFill(*C, fill));
10252   } else { /* scall == MAT_REUSE_MATRIX */
10253     Mat_Product *product = (*C)->product;
10254 
10255     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10256     if (flg && product && product->type != ptype) {
10257       PetscCall(MatProductClear(*C));
10258       product = NULL;
10259     }
10260     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10261     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10262       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10263       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10264       product        = (*C)->product;
10265       product->fill  = fill;
10266       product->clear = PETSC_TRUE;
10267     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10268       flg = PETSC_FALSE;
10269       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10270     }
10271   }
10272   if (flg) {
10273     (*C)->product->api_user = PETSC_TRUE;
10274     PetscCall(MatProductSetType(*C, ptype));
10275     PetscCall(MatProductSetFromOptions(*C));
10276     PetscCall(MatProductSymbolic(*C));
10277   }
10278   PetscCall(MatProductNumeric(*C));
10279   PetscFunctionReturn(PETSC_SUCCESS);
10280 }
10281 
10282 /*@
10283   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10284 
10285   Neighbor-wise Collective
10286 
10287   Input Parameters:
10288 + A     - the left matrix
10289 . B     - the right matrix
10290 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10291 - 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
10292           if the result is a dense matrix this is irrelevant
10293 
10294   Output Parameter:
10295 . C - the product matrix
10296 
10297   Notes:
10298   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10299 
10300   `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
10301   call to this function with `MAT_INITIAL_MATRIX`.
10302 
10303   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10304 
10305   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`,
10306   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10307 
10308   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10309 
10310   Example of Usage:
10311 .vb
10312      MatProductCreate(A,B,NULL,&C);
10313      MatProductSetType(C,MATPRODUCT_AB);
10314      MatProductSymbolic(C);
10315      MatProductNumeric(C); // compute C=A * B
10316      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10317      MatProductNumeric(C);
10318      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10319      MatProductNumeric(C);
10320 .ve
10321 
10322   Level: intermediate
10323 
10324 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10325 @*/
10326 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10327 {
10328   PetscFunctionBegin;
10329   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10330   PetscFunctionReturn(PETSC_SUCCESS);
10331 }
10332 
10333 /*@
10334   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10335 
10336   Neighbor-wise Collective
10337 
10338   Input Parameters:
10339 + A     - the left matrix
10340 . B     - the right matrix
10341 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10342 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10343 
10344   Output Parameter:
10345 . C - the product matrix
10346 
10347   Options Database Key:
10348 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10349               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10350               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10351 
10352   Level: intermediate
10353 
10354   Notes:
10355   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10356 
10357   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10358 
10359   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10360   actually needed.
10361 
10362   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10363   and for pairs of `MATMPIDENSE` matrices.
10364 
10365   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10366 
10367   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10368 
10369 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10370 @*/
10371 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10372 {
10373   PetscFunctionBegin;
10374   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10375   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10376   PetscFunctionReturn(PETSC_SUCCESS);
10377 }
10378 
10379 /*@
10380   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10381 
10382   Neighbor-wise Collective
10383 
10384   Input Parameters:
10385 + A     - the left matrix
10386 . B     - the right matrix
10387 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10388 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10389 
10390   Output Parameter:
10391 . C - the product matrix
10392 
10393   Level: intermediate
10394 
10395   Notes:
10396   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10397 
10398   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10399 
10400   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10401 
10402   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10403   actually needed.
10404 
10405   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10406   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10407 
10408   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10409 
10410 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10411 @*/
10412 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10413 {
10414   PetscFunctionBegin;
10415   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10416   PetscFunctionReturn(PETSC_SUCCESS);
10417 }
10418 
10419 /*@
10420   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10421 
10422   Neighbor-wise Collective
10423 
10424   Input Parameters:
10425 + A     - the left matrix
10426 . B     - the middle matrix
10427 . C     - the right matrix
10428 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10429 - 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
10430           if the result is a dense matrix this is irrelevant
10431 
10432   Output Parameter:
10433 . D - the product matrix
10434 
10435   Level: intermediate
10436 
10437   Notes:
10438   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10439 
10440   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10441 
10442   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10443 
10444   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10445   actually needed.
10446 
10447   If you have many matrices with the same non-zero structure to multiply, you
10448   should use `MAT_REUSE_MATRIX` in all calls but the first
10449 
10450   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10451 
10452 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10453 @*/
10454 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10455 {
10456   PetscFunctionBegin;
10457   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10458   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10459 
10460   if (scall == MAT_INITIAL_MATRIX) {
10461     PetscCall(MatProductCreate(A, B, C, D));
10462     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10463     PetscCall(MatProductSetAlgorithm(*D, "default"));
10464     PetscCall(MatProductSetFill(*D, fill));
10465 
10466     (*D)->product->api_user = PETSC_TRUE;
10467     PetscCall(MatProductSetFromOptions(*D));
10468     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,
10469                ((PetscObject)C)->type_name);
10470     PetscCall(MatProductSymbolic(*D));
10471   } else { /* user may change input matrices when REUSE */
10472     PetscCall(MatProductReplaceMats(A, B, C, *D));
10473   }
10474   PetscCall(MatProductNumeric(*D));
10475   PetscFunctionReturn(PETSC_SUCCESS);
10476 }
10477 
10478 /*@
10479   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10480 
10481   Collective
10482 
10483   Input Parameters:
10484 + mat      - the matrix
10485 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10486 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10487 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10488 
10489   Output Parameter:
10490 . matredundant - redundant matrix
10491 
10492   Level: advanced
10493 
10494   Notes:
10495   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10496   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10497 
10498   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10499   calling it.
10500 
10501   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10502 
10503 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10504 @*/
10505 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10506 {
10507   MPI_Comm       comm;
10508   PetscMPIInt    size;
10509   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10510   Mat_Redundant *redund     = NULL;
10511   PetscSubcomm   psubcomm   = NULL;
10512   MPI_Comm       subcomm_in = subcomm;
10513   Mat           *matseq;
10514   IS             isrow, iscol;
10515   PetscBool      newsubcomm = PETSC_FALSE;
10516 
10517   PetscFunctionBegin;
10518   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10519   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10520     PetscAssertPointer(*matredundant, 5);
10521     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10522   }
10523 
10524   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10525   if (size == 1 || nsubcomm == 1) {
10526     if (reuse == MAT_INITIAL_MATRIX) {
10527       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10528     } else {
10529       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");
10530       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10531     }
10532     PetscFunctionReturn(PETSC_SUCCESS);
10533   }
10534 
10535   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10536   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10537   MatCheckPreallocated(mat, 1);
10538 
10539   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10540   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10541     /* create psubcomm, then get subcomm */
10542     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10543     PetscCallMPI(MPI_Comm_size(comm, &size));
10544     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10545 
10546     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10547     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10548     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10549     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10550     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10551     newsubcomm = PETSC_TRUE;
10552     PetscCall(PetscSubcommDestroy(&psubcomm));
10553   }
10554 
10555   /* get isrow, iscol and a local sequential matrix matseq[0] */
10556   if (reuse == MAT_INITIAL_MATRIX) {
10557     mloc_sub = PETSC_DECIDE;
10558     nloc_sub = PETSC_DECIDE;
10559     if (bs < 1) {
10560       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10561       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10562     } else {
10563       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10564       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10565     }
10566     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10567     rstart = rend - mloc_sub;
10568     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10569     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10570     PetscCall(ISSetIdentity(iscol));
10571   } else { /* reuse == MAT_REUSE_MATRIX */
10572     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");
10573     /* retrieve subcomm */
10574     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10575     redund = (*matredundant)->redundant;
10576     isrow  = redund->isrow;
10577     iscol  = redund->iscol;
10578     matseq = redund->matseq;
10579   }
10580   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10581 
10582   /* get matredundant over subcomm */
10583   if (reuse == MAT_INITIAL_MATRIX) {
10584     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10585 
10586     /* create a supporting struct and attach it to C for reuse */
10587     PetscCall(PetscNew(&redund));
10588     (*matredundant)->redundant = redund;
10589     redund->isrow              = isrow;
10590     redund->iscol              = iscol;
10591     redund->matseq             = matseq;
10592     if (newsubcomm) {
10593       redund->subcomm = subcomm;
10594     } else {
10595       redund->subcomm = MPI_COMM_NULL;
10596     }
10597   } else {
10598     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10599   }
10600 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10601   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10602     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10603     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10604   }
10605 #endif
10606   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10607   PetscFunctionReturn(PETSC_SUCCESS);
10608 }
10609 
10610 /*@C
10611   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10612   a given `Mat`. Each submatrix can span multiple procs.
10613 
10614   Collective
10615 
10616   Input Parameters:
10617 + mat     - the matrix
10618 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10619 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10620 
10621   Output Parameter:
10622 . subMat - parallel sub-matrices each spanning a given `subcomm`
10623 
10624   Level: advanced
10625 
10626   Notes:
10627   The submatrix partition across processors is dictated by `subComm` a
10628   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10629   is not restricted to be grouped with consecutive original MPI processes.
10630 
10631   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10632   map directly to the layout of the original matrix [wrt the local
10633   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10634   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10635   the `subMat`. However the offDiagMat looses some columns - and this is
10636   reconstructed with `MatSetValues()`
10637 
10638   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10639 
10640 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10641 @*/
10642 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10643 {
10644   PetscMPIInt commsize, subCommSize;
10645 
10646   PetscFunctionBegin;
10647   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10648   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10649   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10650 
10651   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");
10652   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10653   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10654   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10655   PetscFunctionReturn(PETSC_SUCCESS);
10656 }
10657 
10658 /*@
10659   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10660 
10661   Not Collective
10662 
10663   Input Parameters:
10664 + mat   - matrix to extract local submatrix from
10665 . isrow - local row indices for submatrix
10666 - iscol - local column indices for submatrix
10667 
10668   Output Parameter:
10669 . submat - the submatrix
10670 
10671   Level: intermediate
10672 
10673   Notes:
10674   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10675 
10676   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10677   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10678 
10679   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10680   `MatSetValuesBlockedLocal()` will also be implemented.
10681 
10682   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10683   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10684 
10685 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10686 @*/
10687 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10688 {
10689   PetscFunctionBegin;
10690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10691   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10692   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10693   PetscCheckSameComm(isrow, 2, iscol, 3);
10694   PetscAssertPointer(submat, 4);
10695   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10696 
10697   if (mat->ops->getlocalsubmatrix) {
10698     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10699   } else {
10700     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10701   }
10702   PetscFunctionReturn(PETSC_SUCCESS);
10703 }
10704 
10705 /*@
10706   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10707 
10708   Not Collective
10709 
10710   Input Parameters:
10711 + mat    - matrix to extract local submatrix from
10712 . isrow  - local row indices for submatrix
10713 . iscol  - local column indices for submatrix
10714 - submat - the submatrix
10715 
10716   Level: intermediate
10717 
10718 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10719 @*/
10720 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10721 {
10722   PetscFunctionBegin;
10723   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10724   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10725   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10726   PetscCheckSameComm(isrow, 2, iscol, 3);
10727   PetscAssertPointer(submat, 4);
10728   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10729 
10730   if (mat->ops->restorelocalsubmatrix) {
10731     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10732   } else {
10733     PetscCall(MatDestroy(submat));
10734   }
10735   *submat = NULL;
10736   PetscFunctionReturn(PETSC_SUCCESS);
10737 }
10738 
10739 /*@
10740   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10741 
10742   Collective
10743 
10744   Input Parameter:
10745 . mat - the matrix
10746 
10747   Output Parameter:
10748 . is - if any rows have zero diagonals this contains the list of them
10749 
10750   Level: developer
10751 
10752 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10753 @*/
10754 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10755 {
10756   PetscFunctionBegin;
10757   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10758   PetscValidType(mat, 1);
10759   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10760   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10761 
10762   if (!mat->ops->findzerodiagonals) {
10763     Vec                diag;
10764     const PetscScalar *a;
10765     PetscInt          *rows;
10766     PetscInt           rStart, rEnd, r, nrow = 0;
10767 
10768     PetscCall(MatCreateVecs(mat, &diag, NULL));
10769     PetscCall(MatGetDiagonal(mat, diag));
10770     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10771     PetscCall(VecGetArrayRead(diag, &a));
10772     for (r = 0; r < rEnd - rStart; ++r)
10773       if (a[r] == 0.0) ++nrow;
10774     PetscCall(PetscMalloc1(nrow, &rows));
10775     nrow = 0;
10776     for (r = 0; r < rEnd - rStart; ++r)
10777       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10778     PetscCall(VecRestoreArrayRead(diag, &a));
10779     PetscCall(VecDestroy(&diag));
10780     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10781   } else {
10782     PetscUseTypeMethod(mat, findzerodiagonals, is);
10783   }
10784   PetscFunctionReturn(PETSC_SUCCESS);
10785 }
10786 
10787 /*@
10788   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10789 
10790   Collective
10791 
10792   Input Parameter:
10793 . mat - the matrix
10794 
10795   Output Parameter:
10796 . is - contains the list of rows with off block diagonal entries
10797 
10798   Level: developer
10799 
10800 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10801 @*/
10802 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10803 {
10804   PetscFunctionBegin;
10805   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10806   PetscValidType(mat, 1);
10807   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10808   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10809 
10810   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10811   PetscFunctionReturn(PETSC_SUCCESS);
10812 }
10813 
10814 /*@C
10815   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10816 
10817   Collective; No Fortran Support
10818 
10819   Input Parameter:
10820 . mat - the matrix
10821 
10822   Output Parameter:
10823 . values - the block inverses in column major order (FORTRAN-like)
10824 
10825   Level: advanced
10826 
10827   Notes:
10828   The size of the blocks is determined by the block size of the matrix.
10829 
10830   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10831 
10832   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10833 
10834 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10835 @*/
10836 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10837 {
10838   PetscFunctionBegin;
10839   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10840   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10841   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10842   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10843   PetscFunctionReturn(PETSC_SUCCESS);
10844 }
10845 
10846 /*@
10847   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10848 
10849   Collective; No Fortran Support
10850 
10851   Input Parameters:
10852 + mat     - the matrix
10853 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10854 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10855 
10856   Output Parameter:
10857 . values - the block inverses in column major order (FORTRAN-like)
10858 
10859   Level: advanced
10860 
10861   Notes:
10862   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10863 
10864   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10865 
10866 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10867 @*/
10868 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10869 {
10870   PetscFunctionBegin;
10871   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10872   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10873   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10874   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10875   PetscFunctionReturn(PETSC_SUCCESS);
10876 }
10877 
10878 /*@
10879   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10880 
10881   Collective
10882 
10883   Input Parameters:
10884 + A - the matrix
10885 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10886 
10887   Level: advanced
10888 
10889   Note:
10890   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10891 
10892 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10893 @*/
10894 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10895 {
10896   const PetscScalar *vals;
10897   PetscInt          *dnnz;
10898   PetscInt           m, rstart, rend, bs, i, j;
10899 
10900   PetscFunctionBegin;
10901   PetscCall(MatInvertBlockDiagonal(A, &vals));
10902   PetscCall(MatGetBlockSize(A, &bs));
10903   PetscCall(MatGetLocalSize(A, &m, NULL));
10904   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10905   PetscCall(PetscMalloc1(m / bs, &dnnz));
10906   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10907   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10908   PetscCall(PetscFree(dnnz));
10909   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10910   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10911   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10912   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10913   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10914   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10915   PetscFunctionReturn(PETSC_SUCCESS);
10916 }
10917 
10918 /*@
10919   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10920   via `MatTransposeColoringCreate()`.
10921 
10922   Collective
10923 
10924   Input Parameter:
10925 . c - coloring context
10926 
10927   Level: intermediate
10928 
10929 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10930 @*/
10931 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10932 {
10933   MatTransposeColoring matcolor = *c;
10934 
10935   PetscFunctionBegin;
10936   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10937   if (--((PetscObject)matcolor)->refct > 0) {
10938     matcolor = NULL;
10939     PetscFunctionReturn(PETSC_SUCCESS);
10940   }
10941 
10942   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10943   PetscCall(PetscFree(matcolor->rows));
10944   PetscCall(PetscFree(matcolor->den2sp));
10945   PetscCall(PetscFree(matcolor->colorforcol));
10946   PetscCall(PetscFree(matcolor->columns));
10947   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10948   PetscCall(PetscHeaderDestroy(c));
10949   PetscFunctionReturn(PETSC_SUCCESS);
10950 }
10951 
10952 /*@
10953   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10954   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10955   `MatTransposeColoring` to sparse `B`.
10956 
10957   Collective
10958 
10959   Input Parameters:
10960 + coloring - coloring context created with `MatTransposeColoringCreate()`
10961 - B        - sparse matrix
10962 
10963   Output Parameter:
10964 . Btdense - dense matrix $B^T$
10965 
10966   Level: developer
10967 
10968   Note:
10969   These are used internally for some implementations of `MatRARt()`
10970 
10971 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10972 @*/
10973 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10974 {
10975   PetscFunctionBegin;
10976   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10977   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10978   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10979 
10980   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10981   PetscFunctionReturn(PETSC_SUCCESS);
10982 }
10983 
10984 /*@
10985   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10986   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10987   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10988   $C_{sp}$ from $C_{den}$.
10989 
10990   Collective
10991 
10992   Input Parameters:
10993 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10994 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10995 
10996   Output Parameter:
10997 . Csp - sparse matrix
10998 
10999   Level: developer
11000 
11001   Note:
11002   These are used internally for some implementations of `MatRARt()`
11003 
11004 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
11005 @*/
11006 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
11007 {
11008   PetscFunctionBegin;
11009   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
11010   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
11011   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
11012 
11013   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
11014   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
11015   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
11016   PetscFunctionReturn(PETSC_SUCCESS);
11017 }
11018 
11019 /*@
11020   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
11021 
11022   Collective
11023 
11024   Input Parameters:
11025 + mat        - the matrix product C
11026 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
11027 
11028   Output Parameter:
11029 . color - the new coloring context
11030 
11031   Level: intermediate
11032 
11033 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
11034           `MatTransColoringApplyDenToSp()`
11035 @*/
11036 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
11037 {
11038   MatTransposeColoring c;
11039   MPI_Comm             comm;
11040 
11041   PetscFunctionBegin;
11042   PetscAssertPointer(color, 3);
11043 
11044   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11045   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11046   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11047   c->ctype = iscoloring->ctype;
11048   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11049   *color = c;
11050   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11051   PetscFunctionReturn(PETSC_SUCCESS);
11052 }
11053 
11054 /*@
11055   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11056   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11057 
11058   Not Collective
11059 
11060   Input Parameter:
11061 . mat - the matrix
11062 
11063   Output Parameter:
11064 . state - the current state
11065 
11066   Level: intermediate
11067 
11068   Notes:
11069   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11070   different matrices
11071 
11072   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11073 
11074   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11075 
11076 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11077 @*/
11078 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11079 {
11080   PetscFunctionBegin;
11081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11082   *state = mat->nonzerostate;
11083   PetscFunctionReturn(PETSC_SUCCESS);
11084 }
11085 
11086 /*@
11087   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11088   matrices from each processor
11089 
11090   Collective
11091 
11092   Input Parameters:
11093 + comm   - the communicators the parallel matrix will live on
11094 . seqmat - the input sequential matrices
11095 . n      - number of local columns (or `PETSC_DECIDE`)
11096 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11097 
11098   Output Parameter:
11099 . mpimat - the parallel matrix generated
11100 
11101   Level: developer
11102 
11103   Note:
11104   The number of columns of the matrix in EACH processor MUST be the same.
11105 
11106 .seealso: [](ch_matrices), `Mat`
11107 @*/
11108 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11109 {
11110   PetscMPIInt size;
11111 
11112   PetscFunctionBegin;
11113   PetscCallMPI(MPI_Comm_size(comm, &size));
11114   if (size == 1) {
11115     if (reuse == MAT_INITIAL_MATRIX) {
11116       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11117     } else {
11118       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11119     }
11120     PetscFunctionReturn(PETSC_SUCCESS);
11121   }
11122 
11123   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");
11124 
11125   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11126   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11127   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11128   PetscFunctionReturn(PETSC_SUCCESS);
11129 }
11130 
11131 /*@
11132   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11133 
11134   Collective
11135 
11136   Input Parameters:
11137 + A - the matrix to create subdomains from
11138 - N - requested number of subdomains
11139 
11140   Output Parameters:
11141 + n   - number of subdomains resulting on this MPI process
11142 - iss - `IS` list with indices of subdomains on this MPI process
11143 
11144   Level: advanced
11145 
11146   Note:
11147   The number of subdomains must be smaller than the communicator size
11148 
11149 .seealso: [](ch_matrices), `Mat`, `IS`
11150 @*/
11151 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11152 {
11153   MPI_Comm    comm, subcomm;
11154   PetscMPIInt size, rank, color;
11155   PetscInt    rstart, rend, k;
11156 
11157   PetscFunctionBegin;
11158   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11159   PetscCallMPI(MPI_Comm_size(comm, &size));
11160   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11161   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);
11162   *n    = 1;
11163   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
11164   color = rank / k;
11165   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11166   PetscCall(PetscMalloc1(1, iss));
11167   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11168   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11169   PetscCallMPI(MPI_Comm_free(&subcomm));
11170   PetscFunctionReturn(PETSC_SUCCESS);
11171 }
11172 
11173 /*@
11174   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11175 
11176   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11177   If they are not the same, uses `MatMatMatMult()`.
11178 
11179   Once the coarse grid problem is constructed, correct for interpolation operators
11180   that are not of full rank, which can legitimately happen in the case of non-nested
11181   geometric multigrid.
11182 
11183   Input Parameters:
11184 + restrct     - restriction operator
11185 . dA          - fine grid matrix
11186 . interpolate - interpolation operator
11187 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11188 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11189 
11190   Output Parameter:
11191 . A - the Galerkin coarse matrix
11192 
11193   Options Database Key:
11194 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11195 
11196   Level: developer
11197 
11198   Note:
11199   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11200 
11201 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11202 @*/
11203 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11204 {
11205   IS  zerorows;
11206   Vec diag;
11207 
11208   PetscFunctionBegin;
11209   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11210   /* Construct the coarse grid matrix */
11211   if (interpolate == restrct) {
11212     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11213   } else {
11214     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11215   }
11216 
11217   /* If the interpolation matrix is not of full rank, A will have zero rows.
11218      This can legitimately happen in the case of non-nested geometric multigrid.
11219      In that event, we set the rows of the matrix to the rows of the identity,
11220      ignoring the equations (as the RHS will also be zero). */
11221 
11222   PetscCall(MatFindZeroRows(*A, &zerorows));
11223 
11224   if (zerorows != NULL) { /* if there are any zero rows */
11225     PetscCall(MatCreateVecs(*A, &diag, NULL));
11226     PetscCall(MatGetDiagonal(*A, diag));
11227     PetscCall(VecISSet(diag, zerorows, 1.0));
11228     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11229     PetscCall(VecDestroy(&diag));
11230     PetscCall(ISDestroy(&zerorows));
11231   }
11232   PetscFunctionReturn(PETSC_SUCCESS);
11233 }
11234 
11235 /*@C
11236   MatSetOperation - Allows user to set a matrix operation for any matrix type
11237 
11238   Logically Collective
11239 
11240   Input Parameters:
11241 + mat - the matrix
11242 . op  - the name of the operation
11243 - f   - the function that provides the operation
11244 
11245   Level: developer
11246 
11247   Example Usage:
11248 .vb
11249   extern PetscErrorCode usermult(Mat, Vec, Vec);
11250 
11251   PetscCall(MatCreateXXX(comm, ..., &A));
11252   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11253 .ve
11254 
11255   Notes:
11256   See the file `include/petscmat.h` for a complete list of matrix
11257   operations, which all have the form MATOP_<OPERATION>, where
11258   <OPERATION> is the name (in all capital letters) of the
11259   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11260 
11261   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11262   sequence as the usual matrix interface routines, since they
11263   are intended to be accessed via the usual matrix interface
11264   routines, e.g.,
11265 .vb
11266   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11267 .ve
11268 
11269   In particular each function MUST return `PETSC_SUCCESS` on success and
11270   nonzero on failure.
11271 
11272   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11273 
11274 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11275 @*/
11276 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11277 {
11278   PetscFunctionBegin;
11279   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11280   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11281   (((void (**)(void))mat->ops)[op]) = f;
11282   PetscFunctionReturn(PETSC_SUCCESS);
11283 }
11284 
11285 /*@C
11286   MatGetOperation - Gets a matrix operation for any matrix type.
11287 
11288   Not Collective
11289 
11290   Input Parameters:
11291 + mat - the matrix
11292 - op  - the name of the operation
11293 
11294   Output Parameter:
11295 . f - the function that provides the operation
11296 
11297   Level: developer
11298 
11299   Example Usage:
11300 .vb
11301   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11302 
11303   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11304 .ve
11305 
11306   Notes:
11307   See the file include/petscmat.h for a complete list of matrix
11308   operations, which all have the form MATOP_<OPERATION>, where
11309   <OPERATION> is the name (in all capital letters) of the
11310   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11311 
11312   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11313 
11314 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11315 @*/
11316 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11317 {
11318   PetscFunctionBegin;
11319   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11320   *f = (((void (**)(void))mat->ops)[op]);
11321   PetscFunctionReturn(PETSC_SUCCESS);
11322 }
11323 
11324 /*@
11325   MatHasOperation - Determines whether the given matrix supports the particular operation.
11326 
11327   Not Collective
11328 
11329   Input Parameters:
11330 + mat - the matrix
11331 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11332 
11333   Output Parameter:
11334 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11335 
11336   Level: advanced
11337 
11338   Note:
11339   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11340 
11341 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11342 @*/
11343 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11344 {
11345   PetscFunctionBegin;
11346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11347   PetscAssertPointer(has, 3);
11348   if (mat->ops->hasoperation) {
11349     PetscUseTypeMethod(mat, hasoperation, op, has);
11350   } else {
11351     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11352     else {
11353       *has = PETSC_FALSE;
11354       if (op == MATOP_CREATE_SUBMATRIX) {
11355         PetscMPIInt size;
11356 
11357         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11358         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11359       }
11360     }
11361   }
11362   PetscFunctionReturn(PETSC_SUCCESS);
11363 }
11364 
11365 /*@
11366   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11367 
11368   Collective
11369 
11370   Input Parameter:
11371 . mat - the matrix
11372 
11373   Output Parameter:
11374 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11375 
11376   Level: beginner
11377 
11378 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11379 @*/
11380 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11381 {
11382   PetscFunctionBegin;
11383   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11384   PetscValidType(mat, 1);
11385   PetscAssertPointer(cong, 2);
11386   if (!mat->rmap || !mat->cmap) {
11387     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11388     PetscFunctionReturn(PETSC_SUCCESS);
11389   }
11390   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11391     PetscCall(PetscLayoutSetUp(mat->rmap));
11392     PetscCall(PetscLayoutSetUp(mat->cmap));
11393     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11394     if (*cong) mat->congruentlayouts = 1;
11395     else mat->congruentlayouts = 0;
11396   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11397   PetscFunctionReturn(PETSC_SUCCESS);
11398 }
11399 
11400 PetscErrorCode MatSetInf(Mat A)
11401 {
11402   PetscFunctionBegin;
11403   PetscUseTypeMethod(A, setinf);
11404   PetscFunctionReturn(PETSC_SUCCESS);
11405 }
11406 
11407 /*@
11408   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
11409   and possibly removes small values from the graph structure.
11410 
11411   Collective
11412 
11413   Input Parameters:
11414 + A       - the matrix
11415 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11416 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11417 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11418 . num_idx - size of 'index' array
11419 - index   - array of block indices to use for graph strength of connection weight
11420 
11421   Output Parameter:
11422 . graph - the resulting graph
11423 
11424   Level: advanced
11425 
11426 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11427 @*/
11428 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11429 {
11430   PetscFunctionBegin;
11431   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11432   PetscValidType(A, 1);
11433   PetscValidLogicalCollectiveBool(A, scale, 3);
11434   PetscAssertPointer(graph, 7);
11435   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11436   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11437   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11438   PetscFunctionReturn(PETSC_SUCCESS);
11439 }
11440 
11441 /*@
11442   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11443   meaning the same memory is used for the matrix, and no new memory is allocated.
11444 
11445   Collective
11446 
11447   Input Parameters:
11448 + A    - the matrix
11449 - 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
11450 
11451   Level: intermediate
11452 
11453   Developer Note:
11454   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11455   of the arrays in the data structure are unneeded.
11456 
11457 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11458 @*/
11459 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11460 {
11461   PetscFunctionBegin;
11462   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11463   PetscUseTypeMethod(A, eliminatezeros, keep);
11464   PetscFunctionReturn(PETSC_SUCCESS);
11465 }
11466