xref: /petsc/src/mat/interface/matrix.c (revision cb0310aa1cf23f9343942574b08b606feca1aed7)
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   PetscCall(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 nonzero pattern provided by the user.
904 
905   Collective
906 
907   Input Parameter:
908 . A - the matrix
909 
910   Level: beginner
911 
912   Notes:
913   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
914 
915   Users can reset the preallocation to access the original memory.
916 
917   Currently only supported for  `MATAIJ` matrices.
918 
919 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
920 @*/
921 PetscErrorCode MatResetPreallocation(Mat A)
922 {
923   PetscFunctionBegin;
924   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
925   PetscValidType(A, 1);
926   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()");
927   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
928   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
929   PetscFunctionReturn(PETSC_SUCCESS);
930 }
931 
932 /*@
933   MatSetUp - Sets up the internal matrix data structures for later use.
934 
935   Collective
936 
937   Input Parameter:
938 . A - the matrix
939 
940   Level: intermediate
941 
942   Notes:
943   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
944   setting values in the matrix.
945 
946   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
947 
948 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
949 @*/
950 PetscErrorCode MatSetUp(Mat A)
951 {
952   PetscFunctionBegin;
953   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
954   if (!((PetscObject)A)->type_name) {
955     PetscMPIInt size;
956 
957     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
958     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
959   }
960   if (!A->preallocated) PetscTryTypeMethod(A, setup);
961   PetscCall(PetscLayoutSetUp(A->rmap));
962   PetscCall(PetscLayoutSetUp(A->cmap));
963   A->preallocated = PETSC_TRUE;
964   PetscFunctionReturn(PETSC_SUCCESS);
965 }
966 
967 #if defined(PETSC_HAVE_SAWS)
968   #include <petscviewersaws.h>
969 #endif
970 
971 /*
972    If threadsafety is on extraneous matrices may be printed
973 
974    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
975 */
976 #if !defined(PETSC_HAVE_THREADSAFETY)
977 static PetscInt insidematview = 0;
978 #endif
979 
980 /*@
981   MatViewFromOptions - View properties of the matrix based on options set in the options database
982 
983   Collective
984 
985   Input Parameters:
986 + A    - the matrix
987 . obj  - optional additional object that provides the options prefix to use
988 - name - command line option
989 
990   Options Database Key:
991 . -mat_view [viewertype]:... - the viewer and its options
992 
993   Level: intermediate
994 
995   Note:
996 .vb
997     If no value is provided ascii:stdout is used
998        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
999                                                   for example ascii::ascii_info prints just the information about the object not all details
1000                                                   unless :append is given filename opens in write mode, overwriting what was already there
1001        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1002        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1003        socket[:port]                             defaults to the standard output port
1004        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1005 .ve
1006 
1007 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1008 @*/
1009 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1010 {
1011   PetscFunctionBegin;
1012   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1013 #if !defined(PETSC_HAVE_THREADSAFETY)
1014   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1015 #endif
1016   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1017   PetscFunctionReturn(PETSC_SUCCESS);
1018 }
1019 
1020 /*@
1021   MatView - display information about a matrix in a variety ways
1022 
1023   Collective on viewer
1024 
1025   Input Parameters:
1026 + mat    - the matrix
1027 - viewer - visualization context
1028 
1029   Options Database Keys:
1030 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1031 . -mat_view ::ascii_info_detail    - Prints more detailed info
1032 . -mat_view                        - Prints matrix in ASCII format
1033 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1034 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1035 . -display <name>                  - Sets display name (default is host)
1036 . -draw_pause <sec>                - Sets number of seconds to pause after display
1037 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1038 . -viewer_socket_machine <machine> - -
1039 . -viewer_socket_port <port>       - -
1040 . -mat_view binary                 - save matrix to file in binary format
1041 - -viewer_binary_filename <name>   - -
1042 
1043   Level: beginner
1044 
1045   Notes:
1046   The available visualization contexts include
1047 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1048 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1049 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1050 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1051 
1052   The user can open alternative visualization contexts with
1053 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1054 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1055   specified file; corresponding input uses `MatLoad()`
1056 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1057   an X window display
1058 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1059   Currently only the `MATSEQDENSE` and `MATAIJ`
1060   matrix types support the Socket viewer.
1061 
1062   The user can call `PetscViewerPushFormat()` to specify the output
1063   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1064   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1065 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1066 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1067 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1068 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1069   format common among all matrix types
1070 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1071   format (which is in many cases the same as the default)
1072 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1073   size and structure (not the matrix entries)
1074 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1075   the matrix structure (still not vector or matrix entries)
1076 
1077   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1078   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1079 
1080   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1081 
1082   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1083   viewer is used.
1084 
1085   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1086   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1087 
1088   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1089   and then use the following mouse functions.
1090 .vb
1091   left mouse: zoom in
1092   middle mouse: zoom out
1093   right mouse: continue with the simulation
1094 .ve
1095 
1096 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1097           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1098 @*/
1099 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1100 {
1101   PetscInt          rows, cols, rbs, cbs;
1102   PetscBool         isascii, isstring, issaws;
1103   PetscViewerFormat format;
1104   PetscMPIInt       size;
1105 
1106   PetscFunctionBegin;
1107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1108   PetscValidType(mat, 1);
1109   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1110   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1111 
1112   PetscCall(PetscViewerGetFormat(viewer, &format));
1113   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1114   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1115 
1116 #if !defined(PETSC_HAVE_THREADSAFETY)
1117   insidematview++;
1118 #endif
1119   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1120   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1121   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1122   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");
1123 
1124   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1125   if (isascii) {
1126     if (!mat->preallocated) {
1127       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1128 #if !defined(PETSC_HAVE_THREADSAFETY)
1129       insidematview--;
1130 #endif
1131       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1132       PetscFunctionReturn(PETSC_SUCCESS);
1133     }
1134     if (!mat->assembled) {
1135       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1136 #if !defined(PETSC_HAVE_THREADSAFETY)
1137       insidematview--;
1138 #endif
1139       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1140       PetscFunctionReturn(PETSC_SUCCESS);
1141     }
1142     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1143     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1144       MatNullSpace nullsp, transnullsp;
1145 
1146       PetscCall(PetscViewerASCIIPushTab(viewer));
1147       PetscCall(MatGetSize(mat, &rows, &cols));
1148       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1149       if (rbs != 1 || cbs != 1) {
1150         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" : ""));
1151         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1152       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1153       if (mat->factortype) {
1154         MatSolverType solver;
1155         PetscCall(MatFactorGetSolverType(mat, &solver));
1156         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1157       }
1158       if (mat->ops->getinfo) {
1159         MatInfo info;
1160         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1161         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1162         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1163       }
1164       PetscCall(MatGetNullSpace(mat, &nullsp));
1165       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1166       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1167       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1168       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1169       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1170       PetscCall(PetscViewerASCIIPushTab(viewer));
1171       PetscCall(MatProductView(mat, viewer));
1172       PetscCall(PetscViewerASCIIPopTab(viewer));
1173       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1174         IS tmp;
1175 
1176         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1177         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1178         PetscCall(PetscViewerASCIIPushTab(viewer));
1179         PetscCall(ISView(tmp, viewer));
1180         PetscCall(PetscViewerASCIIPopTab(viewer));
1181         PetscCall(ISDestroy(&tmp));
1182       }
1183     }
1184   } else if (issaws) {
1185 #if defined(PETSC_HAVE_SAWS)
1186     PetscMPIInt rank;
1187 
1188     PetscCall(PetscObjectName((PetscObject)mat));
1189     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1190     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1191 #endif
1192   } else if (isstring) {
1193     const char *type;
1194     PetscCall(MatGetType(mat, &type));
1195     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1196     PetscTryTypeMethod(mat, view, viewer);
1197   }
1198   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1199     PetscCall(PetscViewerASCIIPushTab(viewer));
1200     PetscUseTypeMethod(mat, viewnative, viewer);
1201     PetscCall(PetscViewerASCIIPopTab(viewer));
1202   } else if (mat->ops->view) {
1203     PetscCall(PetscViewerASCIIPushTab(viewer));
1204     PetscUseTypeMethod(mat, view, viewer);
1205     PetscCall(PetscViewerASCIIPopTab(viewer));
1206   }
1207   if (isascii) {
1208     PetscCall(PetscViewerGetFormat(viewer, &format));
1209     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1210   }
1211   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1212 #if !defined(PETSC_HAVE_THREADSAFETY)
1213   insidematview--;
1214 #endif
1215   PetscFunctionReturn(PETSC_SUCCESS);
1216 }
1217 
1218 #if defined(PETSC_USE_DEBUG)
1219   #include <../src/sys/totalview/tv_data_display.h>
1220 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1221 {
1222   TV_add_row("Local rows", "int", &mat->rmap->n);
1223   TV_add_row("Local columns", "int", &mat->cmap->n);
1224   TV_add_row("Global rows", "int", &mat->rmap->N);
1225   TV_add_row("Global columns", "int", &mat->cmap->N);
1226   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1227   return TV_format_OK;
1228 }
1229 #endif
1230 
1231 /*@
1232   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1233   with `MatView()`.  The matrix format is determined from the options database.
1234   Generates a parallel MPI matrix if the communicator has more than one
1235   processor.  The default matrix type is `MATAIJ`.
1236 
1237   Collective
1238 
1239   Input Parameters:
1240 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1241             or some related function before a call to `MatLoad()`
1242 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1243 
1244   Options Database Key:
1245 . -matload_block_size <bs> - set block size
1246 
1247   Level: beginner
1248 
1249   Notes:
1250   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1251   `Mat` before calling this routine if you wish to set it from the options database.
1252 
1253   `MatLoad()` automatically loads into the options database any options
1254   given in the file filename.info where filename is the name of the file
1255   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1256   file will be ignored if you use the -viewer_binary_skip_info option.
1257 
1258   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1259   sets the default matrix type AIJ and sets the local and global sizes.
1260   If type and/or size is already set, then the same are used.
1261 
1262   In parallel, each processor can load a subset of rows (or the
1263   entire matrix).  This routine is especially useful when a large
1264   matrix is stored on disk and only part of it is desired on each
1265   processor.  For example, a parallel solver may access only some of
1266   the rows from each processor.  The algorithm used here reads
1267   relatively small blocks of data rather than reading the entire
1268   matrix and then subsetting it.
1269 
1270   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1271   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1272   or the sequence like
1273 .vb
1274     `PetscViewer` v;
1275     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1276     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1277     `PetscViewerSetFromOptions`(v);
1278     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1279     `PetscViewerFileSetName`(v,"datafile");
1280 .ve
1281   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1282 $ -viewer_type {binary, hdf5}
1283 
1284   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1285   and src/mat/tutorials/ex10.c with the second approach.
1286 
1287   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1288   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1289   Multiple objects, both matrices and vectors, can be stored within the same file.
1290   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1291 
1292   Most users should not need to know the details of the binary storage
1293   format, since `MatLoad()` and `MatView()` completely hide these details.
1294   But for anyone who is interested, the standard binary matrix storage
1295   format is
1296 
1297 .vb
1298     PetscInt    MAT_FILE_CLASSID
1299     PetscInt    number of rows
1300     PetscInt    number of columns
1301     PetscInt    total number of nonzeros
1302     PetscInt    *number nonzeros in each row
1303     PetscInt    *column indices of all nonzeros (starting index is zero)
1304     PetscScalar *values of all nonzeros
1305 .ve
1306   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1307   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
1308   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1309 
1310   PETSc automatically does the byte swapping for
1311   machines that store the bytes reversed. Thus if you write your own binary
1312   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1313   and `PetscBinaryWrite()` to see how this may be done.
1314 
1315   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1316   Each processor's chunk is loaded independently by its owning MPI process.
1317   Multiple objects, both matrices and vectors, can be stored within the same file.
1318   They are looked up by their PetscObject name.
1319 
1320   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1321   by default the same structure and naming of the AIJ arrays and column count
1322   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1323 $    save example.mat A b -v7.3
1324   can be directly read by this routine (see Reference 1 for details).
1325 
1326   Depending on your MATLAB version, this format might be a default,
1327   otherwise you can set it as default in Preferences.
1328 
1329   Unless -nocompression flag is used to save the file in MATLAB,
1330   PETSc must be configured with ZLIB package.
1331 
1332   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1333 
1334   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1335 
1336   Corresponding `MatView()` is not yet implemented.
1337 
1338   The loaded matrix is actually a transpose of the original one in MATLAB,
1339   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1340   With this format, matrix is automatically transposed by PETSc,
1341   unless the matrix is marked as SPD or symmetric
1342   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1343 
1344   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1345 
1346 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1347  @*/
1348 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1349 {
1350   PetscBool flg;
1351 
1352   PetscFunctionBegin;
1353   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1354   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1355 
1356   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1357 
1358   flg = PETSC_FALSE;
1359   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1360   if (flg) {
1361     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1362     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1363   }
1364   flg = PETSC_FALSE;
1365   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1366   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1367 
1368   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1369   PetscUseTypeMethod(mat, load, viewer);
1370   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1371   PetscFunctionReturn(PETSC_SUCCESS);
1372 }
1373 
1374 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1375 {
1376   Mat_Redundant *redund = *redundant;
1377 
1378   PetscFunctionBegin;
1379   if (redund) {
1380     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1381       PetscCall(ISDestroy(&redund->isrow));
1382       PetscCall(ISDestroy(&redund->iscol));
1383       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1384     } else {
1385       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1386       PetscCall(PetscFree(redund->sbuf_j));
1387       PetscCall(PetscFree(redund->sbuf_a));
1388       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1389         PetscCall(PetscFree(redund->rbuf_j[i]));
1390         PetscCall(PetscFree(redund->rbuf_a[i]));
1391       }
1392       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1393     }
1394 
1395     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1396     PetscCall(PetscFree(redund));
1397   }
1398   PetscFunctionReturn(PETSC_SUCCESS);
1399 }
1400 
1401 /*@
1402   MatDestroy - Frees space taken by a matrix.
1403 
1404   Collective
1405 
1406   Input Parameter:
1407 . A - the matrix
1408 
1409   Level: beginner
1410 
1411   Developer Note:
1412   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1413   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1414   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1415   if changes are needed here.
1416 
1417 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1418 @*/
1419 PetscErrorCode MatDestroy(Mat *A)
1420 {
1421   PetscFunctionBegin;
1422   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1423   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1424   if (--((PetscObject)*A)->refct > 0) {
1425     *A = NULL;
1426     PetscFunctionReturn(PETSC_SUCCESS);
1427   }
1428 
1429   /* if memory was published with SAWs then destroy it */
1430   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1431   PetscTryTypeMethod(*A, destroy);
1432 
1433   PetscCall(PetscFree((*A)->factorprefix));
1434   PetscCall(PetscFree((*A)->defaultvectype));
1435   PetscCall(PetscFree((*A)->defaultrandtype));
1436   PetscCall(PetscFree((*A)->bsizes));
1437   PetscCall(PetscFree((*A)->solvertype));
1438   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1439   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1440   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1441   PetscCall(MatProductClear(*A));
1442   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1443   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1444   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1445   PetscCall(MatDestroy(&(*A)->schur));
1446   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1447   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1448   PetscCall(PetscHeaderDestroy(A));
1449   PetscFunctionReturn(PETSC_SUCCESS);
1450 }
1451 
1452 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1453 /*@
1454   MatSetValues - Inserts or adds a block of values into a matrix.
1455   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1456   MUST be called after all calls to `MatSetValues()` have been completed.
1457 
1458   Not Collective
1459 
1460   Input Parameters:
1461 + mat  - the matrix
1462 . v    - a logically two-dimensional array of values
1463 . m    - the number of rows
1464 . idxm - the global indices of the rows
1465 . n    - the number of columns
1466 . idxn - the global indices of the columns
1467 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1468 
1469   Level: beginner
1470 
1471   Notes:
1472   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1473 
1474   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1475   options cannot be mixed without intervening calls to the assembly
1476   routines.
1477 
1478   `MatSetValues()` uses 0-based row and column numbers in Fortran
1479   as well as in C.
1480 
1481   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1482   simply ignored. This allows easily inserting element stiffness matrices
1483   with homogeneous Dirichlet boundary conditions that you don't want represented
1484   in the matrix.
1485 
1486   Efficiency Alert:
1487   The routine `MatSetValuesBlocked()` may offer much better efficiency
1488   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1489 
1490   Fortran Notes:
1491   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1492 .vb
1493   MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
1494 .ve
1495 
1496   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1497 
1498   Developer Note:
1499   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1500   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1501 
1502 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1503           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1504 @*/
1505 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1506 {
1507   PetscFunctionBeginHot;
1508   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1509   PetscValidType(mat, 1);
1510   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1511   PetscAssertPointer(idxm, 3);
1512   PetscAssertPointer(idxn, 5);
1513   MatCheckPreallocated(mat, 1);
1514 
1515   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1516   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1517 
1518   if (PetscDefined(USE_DEBUG)) {
1519     PetscInt i, j;
1520 
1521     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1522     if (v) {
1523       for (i = 0; i < m; i++) {
1524         for (j = 0; j < n; j++) {
1525           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1526 #if defined(PETSC_USE_COMPLEX)
1527             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1528 #else
1529             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1530 #endif
1531         }
1532       }
1533     }
1534     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1535     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1536   }
1537 
1538   if (mat->assembled) {
1539     mat->was_assembled = PETSC_TRUE;
1540     mat->assembled     = PETSC_FALSE;
1541   }
1542   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1543   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1544   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1545   PetscFunctionReturn(PETSC_SUCCESS);
1546 }
1547 
1548 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1549 /*@
1550   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1551   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1552   MUST be called after all calls to `MatSetValues()` have been completed.
1553 
1554   Not Collective
1555 
1556   Input Parameters:
1557 + mat  - the matrix
1558 . v    - a logically two-dimensional array of values
1559 . ism  - the rows to provide
1560 . isn  - the columns to provide
1561 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1562 
1563   Level: beginner
1564 
1565   Notes:
1566   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1567 
1568   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1569   options cannot be mixed without intervening calls to the assembly
1570   routines.
1571 
1572   `MatSetValues()` uses 0-based row and column numbers in Fortran
1573   as well as in C.
1574 
1575   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1576   simply ignored. This allows easily inserting element stiffness matrices
1577   with homogeneous Dirichlet boundary conditions that you don't want represented
1578   in the matrix.
1579 
1580   Efficiency Alert:
1581   The routine `MatSetValuesBlocked()` may offer much better efficiency
1582   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1583 
1584   This is currently not optimized for any particular `ISType`
1585 
1586   Developer Note:
1587   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1588   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1589 
1590 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1591           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1592 @*/
1593 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1594 {
1595   PetscInt        m, n;
1596   const PetscInt *rows, *cols;
1597 
1598   PetscFunctionBeginHot;
1599   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1600   PetscCall(ISGetIndices(ism, &rows));
1601   PetscCall(ISGetIndices(isn, &cols));
1602   PetscCall(ISGetLocalSize(ism, &m));
1603   PetscCall(ISGetLocalSize(isn, &n));
1604   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1605   PetscCall(ISRestoreIndices(ism, &rows));
1606   PetscCall(ISRestoreIndices(isn, &cols));
1607   PetscFunctionReturn(PETSC_SUCCESS);
1608 }
1609 
1610 /*@
1611   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1612   values into a matrix
1613 
1614   Not Collective
1615 
1616   Input Parameters:
1617 + mat - the matrix
1618 . row - the (block) row to set
1619 - v   - a logically two-dimensional array of values
1620 
1621   Level: intermediate
1622 
1623   Notes:
1624   The values, `v`, are column-oriented (for the block version) and sorted
1625 
1626   All the nonzero values in `row` must be provided
1627 
1628   The matrix must have previously had its column indices set, likely by having been assembled.
1629 
1630   `row` must belong to this MPI process
1631 
1632 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1633           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1634 @*/
1635 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1636 {
1637   PetscInt globalrow;
1638 
1639   PetscFunctionBegin;
1640   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1641   PetscValidType(mat, 1);
1642   PetscAssertPointer(v, 3);
1643   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1644   PetscCall(MatSetValuesRow(mat, globalrow, v));
1645   PetscFunctionReturn(PETSC_SUCCESS);
1646 }
1647 
1648 /*@
1649   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1650   values into a matrix
1651 
1652   Not Collective
1653 
1654   Input Parameters:
1655 + mat - the matrix
1656 . row - the (block) row to set
1657 - v   - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1658 
1659   Level: advanced
1660 
1661   Notes:
1662   The values, `v`, are column-oriented for the block version.
1663 
1664   All the nonzeros in `row` must be provided
1665 
1666   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1667 
1668   `row` must belong to this process
1669 
1670 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1671           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1672 @*/
1673 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1674 {
1675   PetscFunctionBeginHot;
1676   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1677   PetscValidType(mat, 1);
1678   MatCheckPreallocated(mat, 1);
1679   PetscAssertPointer(v, 3);
1680   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1681   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1682   mat->insertmode = INSERT_VALUES;
1683 
1684   if (mat->assembled) {
1685     mat->was_assembled = PETSC_TRUE;
1686     mat->assembled     = PETSC_FALSE;
1687   }
1688   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1689   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1690   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1691   PetscFunctionReturn(PETSC_SUCCESS);
1692 }
1693 
1694 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1695 /*@
1696   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1697   Using structured grid indexing
1698 
1699   Not Collective
1700 
1701   Input Parameters:
1702 + mat  - the matrix
1703 . m    - number of rows being entered
1704 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1705 . n    - number of columns being entered
1706 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1707 . v    - a logically two-dimensional array of values
1708 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1709 
1710   Level: beginner
1711 
1712   Notes:
1713   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1714 
1715   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1716   options cannot be mixed without intervening calls to the assembly
1717   routines.
1718 
1719   The grid coordinates are across the entire grid, not just the local portion
1720 
1721   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1722   as well as in C.
1723 
1724   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1725 
1726   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1727   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1728 
1729   The columns and rows in the stencil passed in MUST be contained within the
1730   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1731   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1732   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1733   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1734 
1735   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1736   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1737   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1738   `DM_BOUNDARY_PERIODIC` boundary type.
1739 
1740   For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1741   a single value per point) you can skip filling those indices.
1742 
1743   Inspired by the structured grid interface to the HYPRE package
1744   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1745 
1746   Efficiency Alert:
1747   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1748   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1749 
1750   Fortran Note:
1751   `idxm` and `idxn` should be declared as
1752 $     MatStencil idxm(4,m),idxn(4,n)
1753   and the values inserted using
1754 .vb
1755     idxm(MatStencil_i,1) = i
1756     idxm(MatStencil_j,1) = j
1757     idxm(MatStencil_k,1) = k
1758     idxm(MatStencil_c,1) = c
1759     etc
1760 .ve
1761 
1762 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1763           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1764 @*/
1765 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1766 {
1767   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1768   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1769   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1770 
1771   PetscFunctionBegin;
1772   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1773   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1774   PetscValidType(mat, 1);
1775   PetscAssertPointer(idxm, 3);
1776   PetscAssertPointer(idxn, 5);
1777 
1778   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1779     jdxm = buf;
1780     jdxn = buf + m;
1781   } else {
1782     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1783     jdxm = bufm;
1784     jdxn = bufn;
1785   }
1786   for (i = 0; i < m; i++) {
1787     for (j = 0; j < 3 - sdim; j++) dxm++;
1788     tmp = *dxm++ - starts[0];
1789     for (j = 0; j < dim - 1; j++) {
1790       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1791       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1792     }
1793     if (mat->stencil.noc) dxm++;
1794     jdxm[i] = tmp;
1795   }
1796   for (i = 0; i < n; i++) {
1797     for (j = 0; j < 3 - sdim; j++) dxn++;
1798     tmp = *dxn++ - starts[0];
1799     for (j = 0; j < dim - 1; j++) {
1800       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1801       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1802     }
1803     if (mat->stencil.noc) dxn++;
1804     jdxn[i] = tmp;
1805   }
1806   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1807   PetscCall(PetscFree2(bufm, bufn));
1808   PetscFunctionReturn(PETSC_SUCCESS);
1809 }
1810 
1811 /*@
1812   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1813   Using structured grid indexing
1814 
1815   Not Collective
1816 
1817   Input Parameters:
1818 + mat  - the matrix
1819 . m    - number of rows being entered
1820 . idxm - grid coordinates for matrix rows being entered
1821 . n    - number of columns being entered
1822 . idxn - grid coordinates for matrix columns being entered
1823 . v    - a logically two-dimensional array of values
1824 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1825 
1826   Level: beginner
1827 
1828   Notes:
1829   By default the values, `v`, are row-oriented and unsorted.
1830   See `MatSetOption()` for other options.
1831 
1832   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1833   options cannot be mixed without intervening calls to the assembly
1834   routines.
1835 
1836   The grid coordinates are across the entire grid, not just the local portion
1837 
1838   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1839   as well as in C.
1840 
1841   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1842 
1843   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1844   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1845 
1846   The columns and rows in the stencil passed in MUST be contained within the
1847   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1848   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1849   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1850   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1851 
1852   Negative indices may be passed in idxm and idxn, these rows and columns are
1853   simply ignored. This allows easily inserting element stiffness matrices
1854   with homogeneous Dirichlet boundary conditions that you don't want represented
1855   in the matrix.
1856 
1857   Inspired by the structured grid interface to the HYPRE package
1858   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1859 
1860   Fortran Note:
1861   `idxm` and `idxn` should be declared as
1862 $     MatStencil idxm(4,m),idxn(4,n)
1863   and the values inserted using
1864 .vb
1865     idxm(MatStencil_i,1) = i
1866     idxm(MatStencil_j,1) = j
1867     idxm(MatStencil_k,1) = k
1868    etc
1869 .ve
1870 
1871 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1872           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1873           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1874 @*/
1875 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1876 {
1877   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1878   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1879   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1880 
1881   PetscFunctionBegin;
1882   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1883   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1884   PetscValidType(mat, 1);
1885   PetscAssertPointer(idxm, 3);
1886   PetscAssertPointer(idxn, 5);
1887   PetscAssertPointer(v, 6);
1888 
1889   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1890     jdxm = buf;
1891     jdxn = buf + m;
1892   } else {
1893     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1894     jdxm = bufm;
1895     jdxn = bufn;
1896   }
1897   for (i = 0; i < m; i++) {
1898     for (j = 0; j < 3 - sdim; j++) dxm++;
1899     tmp = *dxm++ - starts[0];
1900     for (j = 0; j < sdim - 1; j++) {
1901       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1902       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1903     }
1904     dxm++;
1905     jdxm[i] = tmp;
1906   }
1907   for (i = 0; i < n; i++) {
1908     for (j = 0; j < 3 - sdim; j++) dxn++;
1909     tmp = *dxn++ - starts[0];
1910     for (j = 0; j < sdim - 1; j++) {
1911       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1912       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1913     }
1914     dxn++;
1915     jdxn[i] = tmp;
1916   }
1917   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1918   PetscCall(PetscFree2(bufm, bufn));
1919   PetscFunctionReturn(PETSC_SUCCESS);
1920 }
1921 
1922 /*@
1923   MatSetStencil - Sets the grid information for setting values into a matrix via
1924   `MatSetValuesStencil()`
1925 
1926   Not Collective
1927 
1928   Input Parameters:
1929 + mat    - the matrix
1930 . dim    - dimension of the grid 1, 2, or 3
1931 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1932 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1933 - dof    - number of degrees of freedom per node
1934 
1935   Level: beginner
1936 
1937   Notes:
1938   Inspired by the structured grid interface to the HYPRE package
1939   (www.llnl.gov/CASC/hyper)
1940 
1941   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1942   user.
1943 
1944 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1945           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1946 @*/
1947 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1948 {
1949   PetscFunctionBegin;
1950   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1951   PetscAssertPointer(dims, 3);
1952   PetscAssertPointer(starts, 4);
1953 
1954   mat->stencil.dim = dim + (dof > 1);
1955   for (PetscInt i = 0; i < dim; i++) {
1956     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1957     mat->stencil.starts[i] = starts[dim - i - 1];
1958   }
1959   mat->stencil.dims[dim]   = dof;
1960   mat->stencil.starts[dim] = 0;
1961   mat->stencil.noc         = (PetscBool)(dof == 1);
1962   PetscFunctionReturn(PETSC_SUCCESS);
1963 }
1964 
1965 /*@
1966   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1967 
1968   Not Collective
1969 
1970   Input Parameters:
1971 + mat  - the matrix
1972 . v    - a logically two-dimensional array of values
1973 . m    - the number of block rows
1974 . idxm - the global block indices
1975 . n    - the number of block columns
1976 . idxn - the global block indices
1977 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1978 
1979   Level: intermediate
1980 
1981   Notes:
1982   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1983   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1984 
1985   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1986   NOT the total number of rows/columns; for example, if the block size is 2 and
1987   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
1988   The values in `idxm` would be 1 2; that is the first index for each block divided by
1989   the block size.
1990 
1991   You must call `MatSetBlockSize()` when constructing this matrix (before
1992   preallocating it).
1993 
1994   By default the values, `v`, are row-oriented, so the layout of
1995   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1996 
1997   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1998   options cannot be mixed without intervening calls to the assembly
1999   routines.
2000 
2001   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
2002   as well as in C.
2003 
2004   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2005   simply ignored. This allows easily inserting element stiffness matrices
2006   with homogeneous Dirichlet boundary conditions that you don't want represented
2007   in the matrix.
2008 
2009   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2010   internal searching must be done to determine where to place the
2011   data in the matrix storage space.  By instead inserting blocks of
2012   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2013   reduced.
2014 
2015   Example:
2016 .vb
2017    Suppose m=n=2 and block size(bs) = 2 The array is
2018 
2019    1  2  | 3  4
2020    5  6  | 7  8
2021    - - - | - - -
2022    9  10 | 11 12
2023    13 14 | 15 16
2024 
2025    v[] should be passed in like
2026    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2027 
2028   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2029    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2030 .ve
2031 
2032   Fortran Notes:
2033   If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2034 .vb
2035   MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
2036 .ve
2037 
2038   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2039 
2040 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2041 @*/
2042 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2043 {
2044   PetscFunctionBeginHot;
2045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2046   PetscValidType(mat, 1);
2047   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2048   PetscAssertPointer(idxm, 3);
2049   PetscAssertPointer(idxn, 5);
2050   MatCheckPreallocated(mat, 1);
2051   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2052   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2053   if (PetscDefined(USE_DEBUG)) {
2054     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2055     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2056   }
2057   if (PetscDefined(USE_DEBUG)) {
2058     PetscInt rbs, cbs, M, N, i;
2059     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2060     PetscCall(MatGetSize(mat, &M, &N));
2061     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);
2062     for (i = 0; i < n; i++)
2063       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);
2064   }
2065   if (mat->assembled) {
2066     mat->was_assembled = PETSC_TRUE;
2067     mat->assembled     = PETSC_FALSE;
2068   }
2069   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2070   if (mat->ops->setvaluesblocked) {
2071     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2072   } else {
2073     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2074     PetscInt i, j, bs, cbs;
2075 
2076     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2077     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2078       iidxm = buf;
2079       iidxn = buf + m * bs;
2080     } else {
2081       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2082       iidxm = bufr;
2083       iidxn = bufc;
2084     }
2085     for (i = 0; i < m; i++) {
2086       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2087     }
2088     if (m != n || bs != cbs || idxm != idxn) {
2089       for (i = 0; i < n; i++) {
2090         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2091       }
2092     } else iidxn = iidxm;
2093     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2094     PetscCall(PetscFree2(bufr, bufc));
2095   }
2096   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2097   PetscFunctionReturn(PETSC_SUCCESS);
2098 }
2099 
2100 /*@
2101   MatGetValues - Gets a block of local values from a matrix.
2102 
2103   Not Collective; can only return values that are owned by the give process
2104 
2105   Input Parameters:
2106 + mat  - the matrix
2107 . v    - a logically two-dimensional array for storing the values
2108 . m    - the number of rows
2109 . idxm - the  global indices of the rows
2110 . n    - the number of columns
2111 - idxn - the global indices of the columns
2112 
2113   Level: advanced
2114 
2115   Notes:
2116   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2117   The values, `v`, are then returned in a row-oriented format,
2118   analogous to that used by default in `MatSetValues()`.
2119 
2120   `MatGetValues()` uses 0-based row and column numbers in
2121   Fortran as well as in C.
2122 
2123   `MatGetValues()` requires that the matrix has been assembled
2124   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2125   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2126   without intermediate matrix assembly.
2127 
2128   Negative row or column indices will be ignored and those locations in `v` will be
2129   left unchanged.
2130 
2131   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2132   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2133   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2134 
2135 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2136 @*/
2137 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2138 {
2139   PetscFunctionBegin;
2140   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2141   PetscValidType(mat, 1);
2142   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2143   PetscAssertPointer(idxm, 3);
2144   PetscAssertPointer(idxn, 5);
2145   PetscAssertPointer(v, 6);
2146   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2147   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2148   MatCheckPreallocated(mat, 1);
2149 
2150   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2151   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2152   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2153   PetscFunctionReturn(PETSC_SUCCESS);
2154 }
2155 
2156 /*@
2157   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2158   defined previously by `MatSetLocalToGlobalMapping()`
2159 
2160   Not Collective
2161 
2162   Input Parameters:
2163 + mat  - the matrix
2164 . nrow - number of rows
2165 . irow - the row local indices
2166 . ncol - number of columns
2167 - icol - the column local indices
2168 
2169   Output Parameter:
2170 . y - a logically two-dimensional array of values
2171 
2172   Level: advanced
2173 
2174   Notes:
2175   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2176 
2177   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,
2178   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2179   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2180   with `MatSetLocalToGlobalMapping()`.
2181 
2182   Developer Note:
2183   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2184   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2185 
2186 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2187           `MatSetValuesLocal()`, `MatGetValues()`
2188 @*/
2189 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2190 {
2191   PetscFunctionBeginHot;
2192   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2193   PetscValidType(mat, 1);
2194   MatCheckPreallocated(mat, 1);
2195   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2196   PetscAssertPointer(irow, 3);
2197   PetscAssertPointer(icol, 5);
2198   if (PetscDefined(USE_DEBUG)) {
2199     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2200     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2201   }
2202   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2203   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2204   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2205   else {
2206     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2207     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2208       irowm = buf;
2209       icolm = buf + nrow;
2210     } else {
2211       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2212       irowm = bufr;
2213       icolm = bufc;
2214     }
2215     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2216     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2217     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2218     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2219     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2220     PetscCall(PetscFree2(bufr, bufc));
2221   }
2222   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2223   PetscFunctionReturn(PETSC_SUCCESS);
2224 }
2225 
2226 /*@
2227   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2228   the same size. Currently, this can only be called once and creates the given matrix.
2229 
2230   Not Collective
2231 
2232   Input Parameters:
2233 + mat  - the matrix
2234 . nb   - the number of blocks
2235 . bs   - the number of rows (and columns) in each block
2236 . rows - a concatenation of the rows for each block
2237 - v    - a concatenation of logically two-dimensional arrays of values
2238 
2239   Level: advanced
2240 
2241   Notes:
2242   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2243 
2244   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2245 
2246 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2247           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2248 @*/
2249 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2250 {
2251   PetscFunctionBegin;
2252   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2253   PetscValidType(mat, 1);
2254   PetscAssertPointer(rows, 4);
2255   PetscAssertPointer(v, 5);
2256   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2257 
2258   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2259   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2260   else {
2261     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2262   }
2263   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2264   PetscFunctionReturn(PETSC_SUCCESS);
2265 }
2266 
2267 /*@
2268   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2269   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2270   using a local (per-processor) numbering.
2271 
2272   Not Collective
2273 
2274   Input Parameters:
2275 + x        - the matrix
2276 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2277 - cmapping - column mapping
2278 
2279   Level: intermediate
2280 
2281   Note:
2282   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2283 
2284 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2285 @*/
2286 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2287 {
2288   PetscFunctionBegin;
2289   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2290   PetscValidType(x, 1);
2291   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2292   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2293   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2294   else {
2295     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2296     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2297   }
2298   PetscFunctionReturn(PETSC_SUCCESS);
2299 }
2300 
2301 /*@
2302   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2303 
2304   Not Collective
2305 
2306   Input Parameter:
2307 . A - the matrix
2308 
2309   Output Parameters:
2310 + rmapping - row mapping
2311 - cmapping - column mapping
2312 
2313   Level: advanced
2314 
2315 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2316 @*/
2317 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2318 {
2319   PetscFunctionBegin;
2320   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2321   PetscValidType(A, 1);
2322   if (rmapping) {
2323     PetscAssertPointer(rmapping, 2);
2324     *rmapping = A->rmap->mapping;
2325   }
2326   if (cmapping) {
2327     PetscAssertPointer(cmapping, 3);
2328     *cmapping = A->cmap->mapping;
2329   }
2330   PetscFunctionReturn(PETSC_SUCCESS);
2331 }
2332 
2333 /*@
2334   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2335 
2336   Logically Collective
2337 
2338   Input Parameters:
2339 + A    - the matrix
2340 . rmap - row layout
2341 - cmap - column layout
2342 
2343   Level: advanced
2344 
2345   Note:
2346   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2347 
2348 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2349 @*/
2350 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2351 {
2352   PetscFunctionBegin;
2353   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2354   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2355   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2356   PetscFunctionReturn(PETSC_SUCCESS);
2357 }
2358 
2359 /*@
2360   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2361 
2362   Not Collective
2363 
2364   Input Parameter:
2365 . A - the matrix
2366 
2367   Output Parameters:
2368 + rmap - row layout
2369 - cmap - column layout
2370 
2371   Level: advanced
2372 
2373 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2374 @*/
2375 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2376 {
2377   PetscFunctionBegin;
2378   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2379   PetscValidType(A, 1);
2380   if (rmap) {
2381     PetscAssertPointer(rmap, 2);
2382     *rmap = A->rmap;
2383   }
2384   if (cmap) {
2385     PetscAssertPointer(cmap, 3);
2386     *cmap = A->cmap;
2387   }
2388   PetscFunctionReturn(PETSC_SUCCESS);
2389 }
2390 
2391 /*@
2392   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2393   using a local numbering of the rows and columns.
2394 
2395   Not Collective
2396 
2397   Input Parameters:
2398 + mat  - the matrix
2399 . nrow - number of rows
2400 . irow - the row local indices
2401 . ncol - number of columns
2402 . icol - the column local indices
2403 . y    - a logically two-dimensional array of values
2404 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2405 
2406   Level: intermediate
2407 
2408   Notes:
2409   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2410 
2411   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2412   options cannot be mixed without intervening calls to the assembly
2413   routines.
2414 
2415   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2416   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2417 
2418   Fortran Notes:
2419   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2420 .vb
2421   MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2422 .ve
2423 
2424   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2425 
2426   Developer Note:
2427   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2428   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2429 
2430 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2431           `MatGetValuesLocal()`
2432 @*/
2433 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2434 {
2435   PetscFunctionBeginHot;
2436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2437   PetscValidType(mat, 1);
2438   MatCheckPreallocated(mat, 1);
2439   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2440   PetscAssertPointer(irow, 3);
2441   PetscAssertPointer(icol, 5);
2442   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2443   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2444   if (PetscDefined(USE_DEBUG)) {
2445     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2446     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2447   }
2448 
2449   if (mat->assembled) {
2450     mat->was_assembled = PETSC_TRUE;
2451     mat->assembled     = PETSC_FALSE;
2452   }
2453   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2454   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2455   else {
2456     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2457     const PetscInt *irowm, *icolm;
2458 
2459     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2460       bufr  = buf;
2461       bufc  = buf + nrow;
2462       irowm = bufr;
2463       icolm = bufc;
2464     } else {
2465       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2466       irowm = bufr;
2467       icolm = bufc;
2468     }
2469     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2470     else irowm = irow;
2471     if (mat->cmap->mapping) {
2472       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2473         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2474       } else icolm = irowm;
2475     } else icolm = icol;
2476     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2477     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2478   }
2479   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2480   PetscFunctionReturn(PETSC_SUCCESS);
2481 }
2482 
2483 /*@
2484   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2485   using a local ordering of the nodes a block at a time.
2486 
2487   Not Collective
2488 
2489   Input Parameters:
2490 + mat  - the matrix
2491 . nrow - number of rows
2492 . irow - the row local indices
2493 . ncol - number of columns
2494 . icol - the column local indices
2495 . y    - a logically two-dimensional array of values
2496 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2497 
2498   Level: intermediate
2499 
2500   Notes:
2501   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2502   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2503 
2504   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2505   options cannot be mixed without intervening calls to the assembly
2506   routines.
2507 
2508   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2509   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2510 
2511   Fortran Notes:
2512   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2513 .vb
2514   MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2515 .ve
2516 
2517   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2518 
2519   Developer Note:
2520   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2521   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2522 
2523 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2524           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2525 @*/
2526 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2527 {
2528   PetscFunctionBeginHot;
2529   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2530   PetscValidType(mat, 1);
2531   MatCheckPreallocated(mat, 1);
2532   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2533   PetscAssertPointer(irow, 3);
2534   PetscAssertPointer(icol, 5);
2535   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2536   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2537   if (PetscDefined(USE_DEBUG)) {
2538     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2539     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);
2540   }
2541 
2542   if (mat->assembled) {
2543     mat->was_assembled = PETSC_TRUE;
2544     mat->assembled     = PETSC_FALSE;
2545   }
2546   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2547     PetscInt irbs, rbs;
2548     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2549     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2550     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2551   }
2552   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2553     PetscInt icbs, cbs;
2554     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2555     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2556     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2557   }
2558   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2559   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2560   else {
2561     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2562     const PetscInt *irowm, *icolm;
2563 
2564     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2565       bufr  = buf;
2566       bufc  = buf + nrow;
2567       irowm = bufr;
2568       icolm = bufc;
2569     } else {
2570       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2571       irowm = bufr;
2572       icolm = bufc;
2573     }
2574     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2575     else irowm = irow;
2576     if (mat->cmap->mapping) {
2577       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2578         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2579       } else icolm = irowm;
2580     } else icolm = icol;
2581     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2582     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2583   }
2584   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2585   PetscFunctionReturn(PETSC_SUCCESS);
2586 }
2587 
2588 /*@
2589   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2590 
2591   Collective
2592 
2593   Input Parameters:
2594 + mat - the matrix
2595 - x   - the vector to be multiplied
2596 
2597   Output Parameter:
2598 . y - the result
2599 
2600   Level: developer
2601 
2602   Note:
2603   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2604   call `MatMultDiagonalBlock`(A,y,y).
2605 
2606 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2607 @*/
2608 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2609 {
2610   PetscFunctionBegin;
2611   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2612   PetscValidType(mat, 1);
2613   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2614   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2615 
2616   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2617   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2618   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2619   MatCheckPreallocated(mat, 1);
2620 
2621   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2622   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2623   PetscFunctionReturn(PETSC_SUCCESS);
2624 }
2625 
2626 /*@
2627   MatMult - Computes the matrix-vector product, $y = Ax$.
2628 
2629   Neighbor-wise Collective
2630 
2631   Input Parameters:
2632 + mat - the matrix
2633 - x   - the vector to be multiplied
2634 
2635   Output Parameter:
2636 . y - the result
2637 
2638   Level: beginner
2639 
2640   Note:
2641   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2642   call `MatMult`(A,y,y).
2643 
2644 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2645 @*/
2646 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2647 {
2648   PetscFunctionBegin;
2649   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2650   PetscValidType(mat, 1);
2651   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2652   VecCheckAssembled(x);
2653   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2654   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2655   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2656   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2657   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);
2658   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);
2659   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);
2660   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);
2661   PetscCall(VecSetErrorIfLocked(y, 3));
2662   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2663   MatCheckPreallocated(mat, 1);
2664 
2665   PetscCall(VecLockReadPush(x));
2666   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2667   PetscUseTypeMethod(mat, mult, x, y);
2668   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2669   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2670   PetscCall(VecLockReadPop(x));
2671   PetscFunctionReturn(PETSC_SUCCESS);
2672 }
2673 
2674 /*@
2675   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2676 
2677   Neighbor-wise Collective
2678 
2679   Input Parameters:
2680 + mat - the matrix
2681 - x   - the vector to be multiplied
2682 
2683   Output Parameter:
2684 . y - the result
2685 
2686   Level: beginner
2687 
2688   Notes:
2689   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2690   call `MatMultTranspose`(A,y,y).
2691 
2692   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2693   use `MatMultHermitianTranspose()`
2694 
2695 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2696 @*/
2697 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2698 {
2699   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2700 
2701   PetscFunctionBegin;
2702   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2703   PetscValidType(mat, 1);
2704   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2705   VecCheckAssembled(x);
2706   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2707 
2708   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2709   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2710   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2711   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);
2712   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);
2713   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);
2714   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);
2715   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2716   MatCheckPreallocated(mat, 1);
2717 
2718   if (!mat->ops->multtranspose) {
2719     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2720     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);
2721   } else op = mat->ops->multtranspose;
2722   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2723   PetscCall(VecLockReadPush(x));
2724   PetscCall((*op)(mat, x, y));
2725   PetscCall(VecLockReadPop(x));
2726   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2727   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2728   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2729   PetscFunctionReturn(PETSC_SUCCESS);
2730 }
2731 
2732 /*@
2733   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2734 
2735   Neighbor-wise Collective
2736 
2737   Input Parameters:
2738 + mat - the matrix
2739 - x   - the vector to be multiplied
2740 
2741   Output Parameter:
2742 . y - the result
2743 
2744   Level: beginner
2745 
2746   Notes:
2747   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2748   call `MatMultHermitianTranspose`(A,y,y).
2749 
2750   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2751 
2752   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2753 
2754 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2755 @*/
2756 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2757 {
2758   PetscFunctionBegin;
2759   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2760   PetscValidType(mat, 1);
2761   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2762   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2763 
2764   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2765   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2766   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2767   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);
2768   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);
2769   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);
2770   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);
2771   MatCheckPreallocated(mat, 1);
2772 
2773   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2774 #if defined(PETSC_USE_COMPLEX)
2775   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2776     PetscCall(VecLockReadPush(x));
2777     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2778     else PetscUseTypeMethod(mat, mult, x, y);
2779     PetscCall(VecLockReadPop(x));
2780   } else {
2781     Vec w;
2782     PetscCall(VecDuplicate(x, &w));
2783     PetscCall(VecCopy(x, w));
2784     PetscCall(VecConjugate(w));
2785     PetscCall(MatMultTranspose(mat, w, y));
2786     PetscCall(VecDestroy(&w));
2787     PetscCall(VecConjugate(y));
2788   }
2789   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2790 #else
2791   PetscCall(MatMultTranspose(mat, x, y));
2792 #endif
2793   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2794   PetscFunctionReturn(PETSC_SUCCESS);
2795 }
2796 
2797 /*@
2798   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2799 
2800   Neighbor-wise Collective
2801 
2802   Input Parameters:
2803 + mat - the matrix
2804 . v1  - the vector to be multiplied by `mat`
2805 - v2  - the vector to be added to the result
2806 
2807   Output Parameter:
2808 . v3 - the result
2809 
2810   Level: beginner
2811 
2812   Note:
2813   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2814   call `MatMultAdd`(A,v1,v2,v1).
2815 
2816 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2817 @*/
2818 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2819 {
2820   PetscFunctionBegin;
2821   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2822   PetscValidType(mat, 1);
2823   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2824   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2825   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2826 
2827   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2828   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2829   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);
2830   /* 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);
2831      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); */
2832   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);
2833   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);
2834   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2835   MatCheckPreallocated(mat, 1);
2836 
2837   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2838   PetscCall(VecLockReadPush(v1));
2839   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2840   PetscCall(VecLockReadPop(v1));
2841   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2842   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2843   PetscFunctionReturn(PETSC_SUCCESS);
2844 }
2845 
2846 /*@
2847   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2848 
2849   Neighbor-wise Collective
2850 
2851   Input Parameters:
2852 + mat - the matrix
2853 . v1  - the vector to be multiplied by the transpose of the matrix
2854 - v2  - the vector to be added to the result
2855 
2856   Output Parameter:
2857 . v3 - the result
2858 
2859   Level: beginner
2860 
2861   Note:
2862   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2863   call `MatMultTransposeAdd`(A,v1,v2,v1).
2864 
2865 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2866 @*/
2867 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2868 {
2869   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2870 
2871   PetscFunctionBegin;
2872   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2873   PetscValidType(mat, 1);
2874   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2875   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2876   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2877 
2878   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2879   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2880   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);
2881   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);
2882   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);
2883   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2884   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2885   MatCheckPreallocated(mat, 1);
2886 
2887   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2888   PetscCall(VecLockReadPush(v1));
2889   PetscCall((*op)(mat, v1, v2, v3));
2890   PetscCall(VecLockReadPop(v1));
2891   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2892   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2893   PetscFunctionReturn(PETSC_SUCCESS);
2894 }
2895 
2896 /*@
2897   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2898 
2899   Neighbor-wise Collective
2900 
2901   Input Parameters:
2902 + mat - the matrix
2903 . v1  - the vector to be multiplied by the Hermitian transpose
2904 - v2  - the vector to be added to the result
2905 
2906   Output Parameter:
2907 . v3 - the result
2908 
2909   Level: beginner
2910 
2911   Note:
2912   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2913   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2914 
2915 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2916 @*/
2917 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2918 {
2919   PetscFunctionBegin;
2920   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2921   PetscValidType(mat, 1);
2922   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2923   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2924   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2925 
2926   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2927   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2928   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2929   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);
2930   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);
2931   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);
2932   MatCheckPreallocated(mat, 1);
2933 
2934   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2935   PetscCall(VecLockReadPush(v1));
2936   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2937   else {
2938     Vec w, z;
2939     PetscCall(VecDuplicate(v1, &w));
2940     PetscCall(VecCopy(v1, w));
2941     PetscCall(VecConjugate(w));
2942     PetscCall(VecDuplicate(v3, &z));
2943     PetscCall(MatMultTranspose(mat, w, z));
2944     PetscCall(VecDestroy(&w));
2945     PetscCall(VecConjugate(z));
2946     if (v2 != v3) {
2947       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2948     } else {
2949       PetscCall(VecAXPY(v3, 1.0, z));
2950     }
2951     PetscCall(VecDestroy(&z));
2952   }
2953   PetscCall(VecLockReadPop(v1));
2954   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2955   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2956   PetscFunctionReturn(PETSC_SUCCESS);
2957 }
2958 
2959 /*@
2960   MatGetFactorType - gets the type of factorization a matrix is
2961 
2962   Not Collective
2963 
2964   Input Parameter:
2965 . mat - the matrix
2966 
2967   Output Parameter:
2968 . t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2969 
2970   Level: intermediate
2971 
2972 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2973           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2974 @*/
2975 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2976 {
2977   PetscFunctionBegin;
2978   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2979   PetscValidType(mat, 1);
2980   PetscAssertPointer(t, 2);
2981   *t = mat->factortype;
2982   PetscFunctionReturn(PETSC_SUCCESS);
2983 }
2984 
2985 /*@
2986   MatSetFactorType - sets the type of factorization a matrix is
2987 
2988   Logically Collective
2989 
2990   Input Parameters:
2991 + mat - the matrix
2992 - 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`
2993 
2994   Level: intermediate
2995 
2996 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2997           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2998 @*/
2999 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
3000 {
3001   PetscFunctionBegin;
3002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3003   PetscValidType(mat, 1);
3004   mat->factortype = t;
3005   PetscFunctionReturn(PETSC_SUCCESS);
3006 }
3007 
3008 /*@
3009   MatGetInfo - Returns information about matrix storage (number of
3010   nonzeros, memory, etc.).
3011 
3012   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3013 
3014   Input Parameters:
3015 + mat  - the matrix
3016 - 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)
3017 
3018   Output Parameter:
3019 . info - matrix information context
3020 
3021   Options Database Key:
3022 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3023 
3024   Level: intermediate
3025 
3026   Notes:
3027   The `MatInfo` context contains a variety of matrix data, including
3028   number of nonzeros allocated and used, number of mallocs during
3029   matrix assembly, etc.  Additional information for factored matrices
3030   is provided (such as the fill ratio, number of mallocs during
3031   factorization, etc.).
3032 
3033   Example:
3034   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3035   data within the `MatInfo` context.  For example,
3036 .vb
3037       MatInfo info;
3038       Mat     A;
3039       double  mal, nz_a, nz_u;
3040 
3041       MatGetInfo(A, MAT_LOCAL, &info);
3042       mal  = info.mallocs;
3043       nz_a = info.nz_allocated;
3044 .ve
3045 
3046   Fortran Note:
3047   Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters
3048   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
3049   a complete list of parameter names.
3050 .vb
3051       MatInfo info(MAT_INFO_SIZE)
3052       double  precision mal, nz_a
3053       Mat     A
3054       integer ierr
3055 
3056       call MatGetInfo(A, MAT_LOCAL, info, ierr)
3057       mal = info(MAT_INFO_MALLOCS)
3058       nz_a = info(MAT_INFO_NZ_ALLOCATED)
3059 .ve
3060 
3061 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3062 @*/
3063 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3064 {
3065   PetscFunctionBegin;
3066   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3067   PetscValidType(mat, 1);
3068   PetscAssertPointer(info, 3);
3069   MatCheckPreallocated(mat, 1);
3070   PetscUseTypeMethod(mat, getinfo, flag, info);
3071   PetscFunctionReturn(PETSC_SUCCESS);
3072 }
3073 
3074 /*
3075    This is used by external packages where it is not easy to get the info from the actual
3076    matrix factorization.
3077 */
3078 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3079 {
3080   PetscFunctionBegin;
3081   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3082   PetscFunctionReturn(PETSC_SUCCESS);
3083 }
3084 
3085 /*@
3086   MatLUFactor - Performs in-place LU factorization of matrix.
3087 
3088   Collective
3089 
3090   Input Parameters:
3091 + mat  - the matrix
3092 . row  - row permutation
3093 . col  - column permutation
3094 - info - options for factorization, includes
3095 .vb
3096           fill - expected fill as ratio of original fill.
3097           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3098                    Run with the option -info to determine an optimal value to use
3099 .ve
3100 
3101   Level: developer
3102 
3103   Notes:
3104   Most users should employ the `KSP` interface for linear solvers
3105   instead of working directly with matrix algebra routines such as this.
3106   See, e.g., `KSPCreate()`.
3107 
3108   This changes the state of the matrix to a factored matrix; it cannot be used
3109   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3110 
3111   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3112   when not using `KSP`.
3113 
3114   Developer Note:
3115   The Fortran interface is not autogenerated as the
3116   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3117 
3118 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3119           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3120 @*/
3121 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3122 {
3123   MatFactorInfo tinfo;
3124 
3125   PetscFunctionBegin;
3126   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3127   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3128   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3129   if (info) PetscAssertPointer(info, 4);
3130   PetscValidType(mat, 1);
3131   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3132   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3133   MatCheckPreallocated(mat, 1);
3134   if (!info) {
3135     PetscCall(MatFactorInfoInitialize(&tinfo));
3136     info = &tinfo;
3137   }
3138 
3139   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3140   PetscUseTypeMethod(mat, lufactor, row, col, info);
3141   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3142   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3143   PetscFunctionReturn(PETSC_SUCCESS);
3144 }
3145 
3146 /*@
3147   MatILUFactor - Performs in-place ILU factorization of matrix.
3148 
3149   Collective
3150 
3151   Input Parameters:
3152 + mat  - the matrix
3153 . row  - row permutation
3154 . col  - column permutation
3155 - info - structure containing
3156 .vb
3157       levels - number of levels of fill.
3158       expected fill - as ratio of original fill.
3159       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3160                 missing diagonal entries)
3161 .ve
3162 
3163   Level: developer
3164 
3165   Notes:
3166   Most users should employ the `KSP` interface for linear solvers
3167   instead of working directly with matrix algebra routines such as this.
3168   See, e.g., `KSPCreate()`.
3169 
3170   Probably really in-place only when level of fill is zero, otherwise allocates
3171   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3172   when not using `KSP`.
3173 
3174   Developer Note:
3175   The Fortran interface is not autogenerated as the
3176   interface definition cannot be generated correctly [due to MatFactorInfo]
3177 
3178 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3179 @*/
3180 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3181 {
3182   PetscFunctionBegin;
3183   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3184   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3185   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3186   PetscAssertPointer(info, 4);
3187   PetscValidType(mat, 1);
3188   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3189   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3190   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3191   MatCheckPreallocated(mat, 1);
3192 
3193   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3194   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3195   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3196   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3197   PetscFunctionReturn(PETSC_SUCCESS);
3198 }
3199 
3200 /*@
3201   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3202   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3203 
3204   Collective
3205 
3206   Input Parameters:
3207 + fact - the factor matrix obtained with `MatGetFactor()`
3208 . mat  - the matrix
3209 . row  - the row permutation
3210 . col  - the column permutation
3211 - info - options for factorization, includes
3212 .vb
3213           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3214           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3215 .ve
3216 
3217   Level: developer
3218 
3219   Notes:
3220   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3221 
3222   Most users should employ the simplified `KSP` interface for linear solvers
3223   instead of working directly with matrix algebra routines such as this.
3224   See, e.g., `KSPCreate()`.
3225 
3226   Developer Note:
3227   The Fortran interface is not autogenerated as the
3228   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3229 
3230 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3231 @*/
3232 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3233 {
3234   MatFactorInfo tinfo;
3235 
3236   PetscFunctionBegin;
3237   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3238   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3239   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3240   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3241   if (info) PetscAssertPointer(info, 5);
3242   PetscValidType(fact, 1);
3243   PetscValidType(mat, 2);
3244   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3245   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3246   MatCheckPreallocated(mat, 2);
3247   if (!info) {
3248     PetscCall(MatFactorInfoInitialize(&tinfo));
3249     info = &tinfo;
3250   }
3251 
3252   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3253   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3254   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3255   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3256   PetscFunctionReturn(PETSC_SUCCESS);
3257 }
3258 
3259 /*@
3260   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3261   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3262 
3263   Collective
3264 
3265   Input Parameters:
3266 + fact - the factor matrix obtained with `MatGetFactor()`
3267 . mat  - the matrix
3268 - info - options for factorization
3269 
3270   Level: developer
3271 
3272   Notes:
3273   See `MatLUFactor()` for in-place factorization.  See
3274   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3275 
3276   Most users should employ the `KSP` interface for linear solvers
3277   instead of working directly with matrix algebra routines such as this.
3278   See, e.g., `KSPCreate()`.
3279 
3280   Developer Note:
3281   The Fortran interface is not autogenerated as the
3282   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3283 
3284 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3285 @*/
3286 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3287 {
3288   MatFactorInfo tinfo;
3289 
3290   PetscFunctionBegin;
3291   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3292   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3293   PetscValidType(fact, 1);
3294   PetscValidType(mat, 2);
3295   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3296   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,
3297              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3298 
3299   MatCheckPreallocated(mat, 2);
3300   if (!info) {
3301     PetscCall(MatFactorInfoInitialize(&tinfo));
3302     info = &tinfo;
3303   }
3304 
3305   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3306   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3307   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3308   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3309   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3310   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3311   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3312   PetscFunctionReturn(PETSC_SUCCESS);
3313 }
3314 
3315 /*@
3316   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3317   symmetric matrix.
3318 
3319   Collective
3320 
3321   Input Parameters:
3322 + mat  - the matrix
3323 . perm - row and column permutations
3324 - info - expected fill as ratio of original fill
3325 
3326   Level: developer
3327 
3328   Notes:
3329   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3330   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3331 
3332   Most users should employ the `KSP` interface for linear solvers
3333   instead of working directly with matrix algebra routines such as this.
3334   See, e.g., `KSPCreate()`.
3335 
3336   Developer Note:
3337   The Fortran interface is not autogenerated as the
3338   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3339 
3340 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3341           `MatGetOrdering()`
3342 @*/
3343 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3344 {
3345   MatFactorInfo tinfo;
3346 
3347   PetscFunctionBegin;
3348   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3349   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3350   if (info) PetscAssertPointer(info, 3);
3351   PetscValidType(mat, 1);
3352   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3353   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3354   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3355   MatCheckPreallocated(mat, 1);
3356   if (!info) {
3357     PetscCall(MatFactorInfoInitialize(&tinfo));
3358     info = &tinfo;
3359   }
3360 
3361   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3362   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3363   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3364   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3365   PetscFunctionReturn(PETSC_SUCCESS);
3366 }
3367 
3368 /*@
3369   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3370   of a symmetric matrix.
3371 
3372   Collective
3373 
3374   Input Parameters:
3375 + fact - the factor matrix obtained with `MatGetFactor()`
3376 . mat  - the matrix
3377 . perm - row and column permutations
3378 - info - options for factorization, includes
3379 .vb
3380           fill - expected fill as ratio of original fill.
3381           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3382                    Run with the option -info to determine an optimal value to use
3383 .ve
3384 
3385   Level: developer
3386 
3387   Notes:
3388   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3389   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3390 
3391   Most users should employ the `KSP` interface for linear solvers
3392   instead of working directly with matrix algebra routines such as this.
3393   See, e.g., `KSPCreate()`.
3394 
3395   Developer Note:
3396   The Fortran interface is not autogenerated as the
3397   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3398 
3399 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3400           `MatGetOrdering()`
3401 @*/
3402 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3403 {
3404   MatFactorInfo tinfo;
3405 
3406   PetscFunctionBegin;
3407   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3408   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3409   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3410   if (info) PetscAssertPointer(info, 4);
3411   PetscValidType(fact, 1);
3412   PetscValidType(mat, 2);
3413   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3414   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3415   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3416   MatCheckPreallocated(mat, 2);
3417   if (!info) {
3418     PetscCall(MatFactorInfoInitialize(&tinfo));
3419     info = &tinfo;
3420   }
3421 
3422   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3423   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3424   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3425   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3426   PetscFunctionReturn(PETSC_SUCCESS);
3427 }
3428 
3429 /*@
3430   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3431   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3432   `MatCholeskyFactorSymbolic()`.
3433 
3434   Collective
3435 
3436   Input Parameters:
3437 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3438 . mat  - the initial matrix that is to be factored
3439 - info - options for factorization
3440 
3441   Level: developer
3442 
3443   Note:
3444   Most users should employ the `KSP` interface for linear solvers
3445   instead of working directly with matrix algebra routines such as this.
3446   See, e.g., `KSPCreate()`.
3447 
3448   Developer Note:
3449   The Fortran interface is not autogenerated as the
3450   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3451 
3452 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3453 @*/
3454 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3455 {
3456   MatFactorInfo tinfo;
3457 
3458   PetscFunctionBegin;
3459   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3461   PetscValidType(fact, 1);
3462   PetscValidType(mat, 2);
3463   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3464   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,
3465              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3466   MatCheckPreallocated(mat, 2);
3467   if (!info) {
3468     PetscCall(MatFactorInfoInitialize(&tinfo));
3469     info = &tinfo;
3470   }
3471 
3472   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3473   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3474   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3475   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3476   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3477   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3478   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3479   PetscFunctionReturn(PETSC_SUCCESS);
3480 }
3481 
3482 /*@
3483   MatQRFactor - Performs in-place QR factorization of matrix.
3484 
3485   Collective
3486 
3487   Input Parameters:
3488 + mat  - the matrix
3489 . col  - column permutation
3490 - info - options for factorization, includes
3491 .vb
3492           fill - expected fill as ratio of original fill.
3493           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3494                    Run with the option -info to determine an optimal value to use
3495 .ve
3496 
3497   Level: developer
3498 
3499   Notes:
3500   Most users should employ the `KSP` interface for linear solvers
3501   instead of working directly with matrix algebra routines such as this.
3502   See, e.g., `KSPCreate()`.
3503 
3504   This changes the state of the matrix to a factored matrix; it cannot be used
3505   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3506 
3507   Developer Note:
3508   The Fortran interface is not autogenerated as the
3509   interface definition cannot be generated correctly [due to MatFactorInfo]
3510 
3511 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3512           `MatSetUnfactored()`
3513 @*/
3514 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3515 {
3516   PetscFunctionBegin;
3517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3518   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3519   if (info) PetscAssertPointer(info, 3);
3520   PetscValidType(mat, 1);
3521   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3522   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3523   MatCheckPreallocated(mat, 1);
3524   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3525   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3526   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3527   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3528   PetscFunctionReturn(PETSC_SUCCESS);
3529 }
3530 
3531 /*@
3532   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3533   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3534 
3535   Collective
3536 
3537   Input Parameters:
3538 + fact - the factor matrix obtained with `MatGetFactor()`
3539 . mat  - the matrix
3540 . col  - column permutation
3541 - info - options for factorization, includes
3542 .vb
3543           fill - expected fill as ratio of original fill.
3544           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3545                    Run with the option -info to determine an optimal value to use
3546 .ve
3547 
3548   Level: developer
3549 
3550   Note:
3551   Most users should employ the `KSP` interface for linear solvers
3552   instead of working directly with matrix algebra routines such as this.
3553   See, e.g., `KSPCreate()`.
3554 
3555   Developer Note:
3556   The Fortran interface is not autogenerated as the
3557   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3558 
3559 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3560 @*/
3561 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3562 {
3563   MatFactorInfo tinfo;
3564 
3565   PetscFunctionBegin;
3566   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3567   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3568   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3569   if (info) PetscAssertPointer(info, 4);
3570   PetscValidType(fact, 1);
3571   PetscValidType(mat, 2);
3572   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3573   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3574   MatCheckPreallocated(mat, 2);
3575   if (!info) {
3576     PetscCall(MatFactorInfoInitialize(&tinfo));
3577     info = &tinfo;
3578   }
3579 
3580   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3581   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3582   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3583   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3584   PetscFunctionReturn(PETSC_SUCCESS);
3585 }
3586 
3587 /*@
3588   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3589   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3590 
3591   Collective
3592 
3593   Input Parameters:
3594 + fact - the factor matrix obtained with `MatGetFactor()`
3595 . mat  - the matrix
3596 - info - options for factorization
3597 
3598   Level: developer
3599 
3600   Notes:
3601   See `MatQRFactor()` for in-place factorization.
3602 
3603   Most users should employ the `KSP` interface for linear solvers
3604   instead of working directly with matrix algebra routines such as this.
3605   See, e.g., `KSPCreate()`.
3606 
3607   Developer Note:
3608   The Fortran interface is not autogenerated as the
3609   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3610 
3611 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3612 @*/
3613 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3614 {
3615   MatFactorInfo tinfo;
3616 
3617   PetscFunctionBegin;
3618   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3619   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3620   PetscValidType(fact, 1);
3621   PetscValidType(mat, 2);
3622   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3623   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,
3624              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3625 
3626   MatCheckPreallocated(mat, 2);
3627   if (!info) {
3628     PetscCall(MatFactorInfoInitialize(&tinfo));
3629     info = &tinfo;
3630   }
3631 
3632   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3633   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3634   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3635   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3636   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3637   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3638   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3639   PetscFunctionReturn(PETSC_SUCCESS);
3640 }
3641 
3642 /*@
3643   MatSolve - Solves $A x = b$, given a factored matrix.
3644 
3645   Neighbor-wise Collective
3646 
3647   Input Parameters:
3648 + mat - the factored matrix
3649 - b   - the right-hand-side vector
3650 
3651   Output Parameter:
3652 . x - the result vector
3653 
3654   Level: developer
3655 
3656   Notes:
3657   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3658   call `MatSolve`(A,x,x).
3659 
3660   Most users should employ the `KSP` interface for linear solvers
3661   instead of working directly with matrix algebra routines such as this.
3662   See, e.g., `KSPCreate()`.
3663 
3664 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3665 @*/
3666 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3667 {
3668   PetscFunctionBegin;
3669   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3670   PetscValidType(mat, 1);
3671   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3672   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3673   PetscCheckSameComm(mat, 1, b, 2);
3674   PetscCheckSameComm(mat, 1, x, 3);
3675   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3676   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);
3677   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);
3678   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);
3679   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3680   MatCheckPreallocated(mat, 1);
3681 
3682   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3683   PetscCall(VecFlag(x, mat->factorerrortype));
3684   if (mat->factorerrortype) {
3685     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3686   } else PetscUseTypeMethod(mat, solve, b, x);
3687   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3688   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3689   PetscFunctionReturn(PETSC_SUCCESS);
3690 }
3691 
3692 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3693 {
3694   Vec      b, x;
3695   PetscInt N, i;
3696   PetscErrorCode (*f)(Mat, Vec, Vec);
3697   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3698 
3699   PetscFunctionBegin;
3700   if (A->factorerrortype) {
3701     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3702     PetscCall(MatSetInf(X));
3703     PetscFunctionReturn(PETSC_SUCCESS);
3704   }
3705   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3706   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3707   PetscCall(MatBoundToCPU(A, &Abound));
3708   if (!Abound) {
3709     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3710     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3711   }
3712 #if PetscDefined(HAVE_CUDA)
3713   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3714   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3715 #elif PetscDefined(HAVE_HIP)
3716   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3717   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3718 #endif
3719   PetscCall(MatGetSize(B, NULL, &N));
3720   for (i = 0; i < N; i++) {
3721     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3722     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3723     PetscCall((*f)(A, b, x));
3724     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3725     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3726   }
3727   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3728   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3729   PetscFunctionReturn(PETSC_SUCCESS);
3730 }
3731 
3732 /*@
3733   MatMatSolve - Solves $A X = B$, given a factored matrix.
3734 
3735   Neighbor-wise Collective
3736 
3737   Input Parameters:
3738 + A - the factored matrix
3739 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3740 
3741   Output Parameter:
3742 . X - the result matrix (dense matrix)
3743 
3744   Level: developer
3745 
3746   Note:
3747   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3748   otherwise, `B` and `X` cannot be the same.
3749 
3750 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3751 @*/
3752 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3753 {
3754   PetscFunctionBegin;
3755   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3756   PetscValidType(A, 1);
3757   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3758   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3759   PetscCheckSameComm(A, 1, B, 2);
3760   PetscCheckSameComm(A, 1, X, 3);
3761   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);
3762   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);
3763   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");
3764   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3765   MatCheckPreallocated(A, 1);
3766 
3767   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3768   if (!A->ops->matsolve) {
3769     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3770     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3771   } else PetscUseTypeMethod(A, matsolve, B, X);
3772   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3773   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3774   PetscFunctionReturn(PETSC_SUCCESS);
3775 }
3776 
3777 /*@
3778   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3779 
3780   Neighbor-wise Collective
3781 
3782   Input Parameters:
3783 + A - the factored matrix
3784 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3785 
3786   Output Parameter:
3787 . X - the result matrix (dense matrix)
3788 
3789   Level: developer
3790 
3791   Note:
3792   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3793   call `MatMatSolveTranspose`(A,X,X).
3794 
3795 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3796 @*/
3797 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3798 {
3799   PetscFunctionBegin;
3800   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3801   PetscValidType(A, 1);
3802   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3803   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3804   PetscCheckSameComm(A, 1, B, 2);
3805   PetscCheckSameComm(A, 1, X, 3);
3806   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3807   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);
3808   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);
3809   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);
3810   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");
3811   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3812   MatCheckPreallocated(A, 1);
3813 
3814   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3815   if (!A->ops->matsolvetranspose) {
3816     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3817     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3818   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3819   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3820   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3821   PetscFunctionReturn(PETSC_SUCCESS);
3822 }
3823 
3824 /*@
3825   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3826 
3827   Neighbor-wise Collective
3828 
3829   Input Parameters:
3830 + A  - the factored matrix
3831 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3832 
3833   Output Parameter:
3834 . X - the result matrix (dense matrix)
3835 
3836   Level: developer
3837 
3838   Note:
3839   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
3840   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3841 
3842 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3843 @*/
3844 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3845 {
3846   PetscFunctionBegin;
3847   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3848   PetscValidType(A, 1);
3849   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3850   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3851   PetscCheckSameComm(A, 1, Bt, 2);
3852   PetscCheckSameComm(A, 1, X, 3);
3853 
3854   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3855   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);
3856   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);
3857   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");
3858   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3859   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3860   MatCheckPreallocated(A, 1);
3861 
3862   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3863   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3864   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3865   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3866   PetscFunctionReturn(PETSC_SUCCESS);
3867 }
3868 
3869 /*@
3870   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3871   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3872 
3873   Neighbor-wise Collective
3874 
3875   Input Parameters:
3876 + mat - the factored matrix
3877 - b   - the right-hand-side vector
3878 
3879   Output Parameter:
3880 . x - the result vector
3881 
3882   Level: developer
3883 
3884   Notes:
3885   `MatSolve()` should be used for most applications, as it performs
3886   a forward solve followed by a backward solve.
3887 
3888   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3889   call `MatForwardSolve`(A,x,x).
3890 
3891   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3892   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3893   `MatForwardSolve()` solves $U^T*D y = b$, and
3894   `MatBackwardSolve()` solves $U x = y$.
3895   Thus they do not provide a symmetric preconditioner.
3896 
3897 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3898 @*/
3899 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3900 {
3901   PetscFunctionBegin;
3902   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3903   PetscValidType(mat, 1);
3904   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3905   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3906   PetscCheckSameComm(mat, 1, b, 2);
3907   PetscCheckSameComm(mat, 1, x, 3);
3908   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3909   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);
3910   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);
3911   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);
3912   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3913   MatCheckPreallocated(mat, 1);
3914 
3915   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3916   PetscUseTypeMethod(mat, forwardsolve, b, x);
3917   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3918   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3919   PetscFunctionReturn(PETSC_SUCCESS);
3920 }
3921 
3922 /*@
3923   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3924   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3925 
3926   Neighbor-wise Collective
3927 
3928   Input Parameters:
3929 + mat - the factored matrix
3930 - b   - the right-hand-side vector
3931 
3932   Output Parameter:
3933 . x - the result vector
3934 
3935   Level: developer
3936 
3937   Notes:
3938   `MatSolve()` should be used for most applications, as it performs
3939   a forward solve followed by a backward solve.
3940 
3941   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3942   call `MatBackwardSolve`(A,x,x).
3943 
3944   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3945   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3946   `MatForwardSolve()` solves $U^T*D y = b$, and
3947   `MatBackwardSolve()` solves $U x = y$.
3948   Thus they do not provide a symmetric preconditioner.
3949 
3950 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3951 @*/
3952 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3953 {
3954   PetscFunctionBegin;
3955   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3956   PetscValidType(mat, 1);
3957   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3958   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3959   PetscCheckSameComm(mat, 1, b, 2);
3960   PetscCheckSameComm(mat, 1, x, 3);
3961   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3962   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);
3963   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);
3964   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);
3965   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3966   MatCheckPreallocated(mat, 1);
3967 
3968   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3969   PetscUseTypeMethod(mat, backwardsolve, b, x);
3970   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3971   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3972   PetscFunctionReturn(PETSC_SUCCESS);
3973 }
3974 
3975 /*@
3976   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3977 
3978   Neighbor-wise Collective
3979 
3980   Input Parameters:
3981 + mat - the factored matrix
3982 . b   - the right-hand-side vector
3983 - y   - the vector to be added to
3984 
3985   Output Parameter:
3986 . x - the result vector
3987 
3988   Level: developer
3989 
3990   Note:
3991   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3992   call `MatSolveAdd`(A,x,y,x).
3993 
3994 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3995 @*/
3996 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3997 {
3998   PetscScalar one = 1.0;
3999   Vec         tmp;
4000 
4001   PetscFunctionBegin;
4002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4003   PetscValidType(mat, 1);
4004   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4005   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4006   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4007   PetscCheckSameComm(mat, 1, b, 2);
4008   PetscCheckSameComm(mat, 1, y, 3);
4009   PetscCheckSameComm(mat, 1, x, 4);
4010   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4011   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);
4012   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);
4013   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);
4014   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);
4015   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);
4016   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4017   MatCheckPreallocated(mat, 1);
4018 
4019   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4020   PetscCall(VecFlag(x, mat->factorerrortype));
4021   if (mat->factorerrortype) {
4022     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4023   } else if (mat->ops->solveadd) {
4024     PetscUseTypeMethod(mat, solveadd, b, y, x);
4025   } else {
4026     /* do the solve then the add manually */
4027     if (x != y) {
4028       PetscCall(MatSolve(mat, b, x));
4029       PetscCall(VecAXPY(x, one, y));
4030     } else {
4031       PetscCall(VecDuplicate(x, &tmp));
4032       PetscCall(VecCopy(x, tmp));
4033       PetscCall(MatSolve(mat, b, x));
4034       PetscCall(VecAXPY(x, one, tmp));
4035       PetscCall(VecDestroy(&tmp));
4036     }
4037   }
4038   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4039   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4040   PetscFunctionReturn(PETSC_SUCCESS);
4041 }
4042 
4043 /*@
4044   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4045 
4046   Neighbor-wise Collective
4047 
4048   Input Parameters:
4049 + mat - the factored matrix
4050 - b   - the right-hand-side vector
4051 
4052   Output Parameter:
4053 . x - the result vector
4054 
4055   Level: developer
4056 
4057   Notes:
4058   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4059   call `MatSolveTranspose`(A,x,x).
4060 
4061   Most users should employ the `KSP` interface for linear solvers
4062   instead of working directly with matrix algebra routines such as this.
4063   See, e.g., `KSPCreate()`.
4064 
4065 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4066 @*/
4067 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4068 {
4069   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4070 
4071   PetscFunctionBegin;
4072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4073   PetscValidType(mat, 1);
4074   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4075   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4076   PetscCheckSameComm(mat, 1, b, 2);
4077   PetscCheckSameComm(mat, 1, x, 3);
4078   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4079   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);
4080   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);
4081   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4082   MatCheckPreallocated(mat, 1);
4083   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4084   PetscCall(VecFlag(x, mat->factorerrortype));
4085   if (mat->factorerrortype) {
4086     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4087   } else {
4088     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4089     PetscCall((*f)(mat, b, x));
4090   }
4091   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4092   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4093   PetscFunctionReturn(PETSC_SUCCESS);
4094 }
4095 
4096 /*@
4097   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4098   factored matrix.
4099 
4100   Neighbor-wise Collective
4101 
4102   Input Parameters:
4103 + mat - the factored matrix
4104 . b   - the right-hand-side vector
4105 - y   - the vector to be added to
4106 
4107   Output Parameter:
4108 . x - the result vector
4109 
4110   Level: developer
4111 
4112   Note:
4113   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4114   call `MatSolveTransposeAdd`(A,x,y,x).
4115 
4116 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4117 @*/
4118 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4119 {
4120   PetscScalar one = 1.0;
4121   Vec         tmp;
4122   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4123 
4124   PetscFunctionBegin;
4125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4126   PetscValidType(mat, 1);
4127   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4128   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4129   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4130   PetscCheckSameComm(mat, 1, b, 2);
4131   PetscCheckSameComm(mat, 1, y, 3);
4132   PetscCheckSameComm(mat, 1, x, 4);
4133   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4134   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);
4135   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);
4136   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);
4137   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);
4138   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4139   MatCheckPreallocated(mat, 1);
4140 
4141   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4142   PetscCall(VecFlag(x, mat->factorerrortype));
4143   if (mat->factorerrortype) {
4144     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4145   } else if (f) {
4146     PetscCall((*f)(mat, b, y, x));
4147   } else {
4148     /* do the solve then the add manually */
4149     if (x != y) {
4150       PetscCall(MatSolveTranspose(mat, b, x));
4151       PetscCall(VecAXPY(x, one, y));
4152     } else {
4153       PetscCall(VecDuplicate(x, &tmp));
4154       PetscCall(VecCopy(x, tmp));
4155       PetscCall(MatSolveTranspose(mat, b, x));
4156       PetscCall(VecAXPY(x, one, tmp));
4157       PetscCall(VecDestroy(&tmp));
4158     }
4159   }
4160   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4161   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4162   PetscFunctionReturn(PETSC_SUCCESS);
4163 }
4164 
4165 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4166 /*@
4167   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4168 
4169   Neighbor-wise Collective
4170 
4171   Input Parameters:
4172 + mat   - the matrix
4173 . b     - the right-hand side
4174 . omega - the relaxation factor
4175 . flag  - flag indicating the type of SOR (see below)
4176 . shift - diagonal shift
4177 . its   - the number of iterations
4178 - lits  - the number of local iterations
4179 
4180   Output Parameter:
4181 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4182 
4183   SOR Flags:
4184 +     `SOR_FORWARD_SWEEP` - forward SOR
4185 .     `SOR_BACKWARD_SWEEP` - backward SOR
4186 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4187 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4188 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4189 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4190 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4191 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4192   upper/lower triangular part of matrix to
4193   vector (with omega)
4194 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4195 
4196   Level: developer
4197 
4198   Notes:
4199   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4200   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4201   on each processor.
4202 
4203   Application programmers will not generally use `MatSOR()` directly,
4204   but instead will employ the `KSP`/`PC` interface.
4205 
4206   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4207 
4208   Most users should employ the `KSP` interface for linear solvers
4209   instead of working directly with matrix algebra routines such as this.
4210   See, e.g., `KSPCreate()`.
4211 
4212   Vectors `x` and `b` CANNOT be the same
4213 
4214   The flags are implemented as bitwise inclusive or operations.
4215   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4216   to specify a zero initial guess for SSOR.
4217 
4218   Developer Note:
4219   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4220 
4221 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4222 @*/
4223 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4224 {
4225   PetscFunctionBegin;
4226   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4227   PetscValidType(mat, 1);
4228   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4229   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4230   PetscCheckSameComm(mat, 1, b, 2);
4231   PetscCheckSameComm(mat, 1, x, 8);
4232   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4233   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4234   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);
4235   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);
4236   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);
4237   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4238   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4239   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4240 
4241   MatCheckPreallocated(mat, 1);
4242   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4243   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4244   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4245   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4246   PetscFunctionReturn(PETSC_SUCCESS);
4247 }
4248 
4249 /*
4250       Default matrix copy routine.
4251 */
4252 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4253 {
4254   PetscInt           i, rstart = 0, rend = 0, nz;
4255   const PetscInt    *cwork;
4256   const PetscScalar *vwork;
4257 
4258   PetscFunctionBegin;
4259   if (B->assembled) PetscCall(MatZeroEntries(B));
4260   if (str == SAME_NONZERO_PATTERN) {
4261     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4262     for (i = rstart; i < rend; i++) {
4263       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4264       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4265       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4266     }
4267   } else {
4268     PetscCall(MatAYPX(B, 0.0, A, str));
4269   }
4270   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4271   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4272   PetscFunctionReturn(PETSC_SUCCESS);
4273 }
4274 
4275 /*@
4276   MatCopy - Copies a matrix to another matrix.
4277 
4278   Collective
4279 
4280   Input Parameters:
4281 + A   - the matrix
4282 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4283 
4284   Output Parameter:
4285 . B - where the copy is put
4286 
4287   Level: intermediate
4288 
4289   Notes:
4290   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4291 
4292   `MatCopy()` copies the matrix entries of a matrix to another existing
4293   matrix (after first zeroing the second matrix).  A related routine is
4294   `MatConvert()`, which first creates a new matrix and then copies the data.
4295 
4296 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4297 @*/
4298 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4299 {
4300   PetscInt i;
4301 
4302   PetscFunctionBegin;
4303   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4304   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4305   PetscValidType(A, 1);
4306   PetscValidType(B, 2);
4307   PetscCheckSameComm(A, 1, B, 2);
4308   MatCheckPreallocated(B, 2);
4309   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4310   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4311   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,
4312              A->cmap->N, B->cmap->N);
4313   MatCheckPreallocated(A, 1);
4314   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4315 
4316   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4317   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4318   else PetscCall(MatCopy_Basic(A, B, str));
4319 
4320   B->stencil.dim = A->stencil.dim;
4321   B->stencil.noc = A->stencil.noc;
4322   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4323     B->stencil.dims[i]   = A->stencil.dims[i];
4324     B->stencil.starts[i] = A->stencil.starts[i];
4325   }
4326 
4327   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4328   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4329   PetscFunctionReturn(PETSC_SUCCESS);
4330 }
4331 
4332 /*@
4333   MatConvert - Converts a matrix to another matrix, either of the same
4334   or different type.
4335 
4336   Collective
4337 
4338   Input Parameters:
4339 + mat     - the matrix
4340 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4341             same type as the original matrix.
4342 - reuse   - denotes if the destination matrix is to be created or reused.
4343             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
4344             `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).
4345 
4346   Output Parameter:
4347 . M - pointer to place new matrix
4348 
4349   Level: intermediate
4350 
4351   Notes:
4352   `MatConvert()` first creates a new matrix and then copies the data from
4353   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4354   entries of one matrix to another already existing matrix context.
4355 
4356   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4357   the MPI communicator of the generated matrix is always the same as the communicator
4358   of the input matrix.
4359 
4360 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4361 @*/
4362 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4363 {
4364   PetscBool  sametype, issame, flg;
4365   PetscBool3 issymmetric, ishermitian;
4366   char       convname[256], mtype[256];
4367   Mat        B;
4368 
4369   PetscFunctionBegin;
4370   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4371   PetscValidType(mat, 1);
4372   PetscAssertPointer(M, 4);
4373   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4374   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4375   MatCheckPreallocated(mat, 1);
4376 
4377   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4378   if (flg) newtype = mtype;
4379 
4380   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4381   PetscCall(PetscStrcmp(newtype, "same", &issame));
4382   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4383   if (reuse == MAT_REUSE_MATRIX) {
4384     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4385     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4386   }
4387 
4388   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4389     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4390     PetscFunctionReturn(PETSC_SUCCESS);
4391   }
4392 
4393   /* Cache Mat options because some converters use MatHeaderReplace  */
4394   issymmetric = mat->symmetric;
4395   ishermitian = mat->hermitian;
4396 
4397   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4398     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4399     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4400   } else {
4401     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4402     const char *prefix[3]                                 = {"seq", "mpi", ""};
4403     PetscInt    i;
4404     /*
4405        Order of precedence:
4406        0) See if newtype is a superclass of the current matrix.
4407        1) See if a specialized converter is known to the current matrix.
4408        2) See if a specialized converter is known to the desired matrix class.
4409        3) See if a good general converter is registered for the desired class
4410           (as of 6/27/03 only MATMPIADJ falls into this category).
4411        4) See if a good general converter is known for the current matrix.
4412        5) Use a really basic converter.
4413     */
4414 
4415     /* 0) See if newtype is a superclass of the current matrix.
4416           i.e mat is mpiaij and newtype is aij */
4417     for (i = 0; i < 2; i++) {
4418       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4419       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4420       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4421       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4422       if (flg) {
4423         if (reuse == MAT_INPLACE_MATRIX) {
4424           PetscCall(PetscInfo(mat, "Early return\n"));
4425           PetscFunctionReturn(PETSC_SUCCESS);
4426         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4427           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4428           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4429           PetscFunctionReturn(PETSC_SUCCESS);
4430         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4431           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4432           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4433           PetscFunctionReturn(PETSC_SUCCESS);
4434         }
4435       }
4436     }
4437     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4438     for (i = 0; i < 3; i++) {
4439       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4440       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4441       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4442       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4443       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4444       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4445       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4446       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4447       if (conv) goto foundconv;
4448     }
4449 
4450     /* 2)  See if a specialized converter is known to the desired matrix class. */
4451     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4452     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4453     PetscCall(MatSetType(B, newtype));
4454     for (i = 0; i < 3; i++) {
4455       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4456       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4457       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4458       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4459       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4460       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4461       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4462       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4463       if (conv) {
4464         PetscCall(MatDestroy(&B));
4465         goto foundconv;
4466       }
4467     }
4468 
4469     /* 3) See if a good general converter is registered for the desired class */
4470     conv = B->ops->convertfrom;
4471     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4472     PetscCall(MatDestroy(&B));
4473     if (conv) goto foundconv;
4474 
4475     /* 4) See if a good general converter is known for the current matrix */
4476     if (mat->ops->convert) conv = mat->ops->convert;
4477     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4478     if (conv) goto foundconv;
4479 
4480     /* 5) Use a really basic converter. */
4481     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4482     conv = MatConvert_Basic;
4483 
4484   foundconv:
4485     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4486     PetscCall((*conv)(mat, newtype, reuse, M));
4487     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4488       /* the block sizes must be same if the mappings are copied over */
4489       (*M)->rmap->bs = mat->rmap->bs;
4490       (*M)->cmap->bs = mat->cmap->bs;
4491       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4492       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4493       (*M)->rmap->mapping = mat->rmap->mapping;
4494       (*M)->cmap->mapping = mat->cmap->mapping;
4495     }
4496     (*M)->stencil.dim = mat->stencil.dim;
4497     (*M)->stencil.noc = mat->stencil.noc;
4498     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4499       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4500       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4501     }
4502     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4503   }
4504   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4505 
4506   /* Copy Mat options */
4507   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4508   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4509   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4510   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4511   PetscFunctionReturn(PETSC_SUCCESS);
4512 }
4513 
4514 /*@
4515   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4516 
4517   Not Collective
4518 
4519   Input Parameter:
4520 . mat - the matrix, must be a factored matrix
4521 
4522   Output Parameter:
4523 . type - the string name of the package (do not free this string)
4524 
4525   Level: intermediate
4526 
4527   Fortran Note:
4528   Pass in an empty string that is long enough and the package name will be copied into it.
4529 
4530 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4531 @*/
4532 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4533 {
4534   PetscErrorCode (*conv)(Mat, MatSolverType *);
4535 
4536   PetscFunctionBegin;
4537   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4538   PetscValidType(mat, 1);
4539   PetscAssertPointer(type, 2);
4540   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4541   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4542   if (conv) PetscCall((*conv)(mat, type));
4543   else *type = MATSOLVERPETSC;
4544   PetscFunctionReturn(PETSC_SUCCESS);
4545 }
4546 
4547 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4548 struct _MatSolverTypeForSpecifcType {
4549   MatType mtype;
4550   /* no entry for MAT_FACTOR_NONE */
4551   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4552   MatSolverTypeForSpecifcType next;
4553 };
4554 
4555 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4556 struct _MatSolverTypeHolder {
4557   char                       *name;
4558   MatSolverTypeForSpecifcType handlers;
4559   MatSolverTypeHolder         next;
4560 };
4561 
4562 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4563 
4564 /*@C
4565   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4566 
4567   Logically Collective, No Fortran Support
4568 
4569   Input Parameters:
4570 + package      - name of the package, for example petsc or superlu
4571 . mtype        - the matrix type that works with this package
4572 . ftype        - the type of factorization supported by the package
4573 - createfactor - routine that will create the factored matrix ready to be used
4574 
4575   Level: developer
4576 
4577 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4578   `MatGetFactor()`
4579 @*/
4580 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4581 {
4582   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4583   PetscBool                   flg;
4584   MatSolverTypeForSpecifcType inext, iprev = NULL;
4585 
4586   PetscFunctionBegin;
4587   PetscCall(MatInitializePackage());
4588   if (!next) {
4589     PetscCall(PetscNew(&MatSolverTypeHolders));
4590     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4591     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4592     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4593     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4594     PetscFunctionReturn(PETSC_SUCCESS);
4595   }
4596   while (next) {
4597     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4598     if (flg) {
4599       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4600       inext = next->handlers;
4601       while (inext) {
4602         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4603         if (flg) {
4604           inext->createfactor[(int)ftype - 1] = createfactor;
4605           PetscFunctionReturn(PETSC_SUCCESS);
4606         }
4607         iprev = inext;
4608         inext = inext->next;
4609       }
4610       PetscCall(PetscNew(&iprev->next));
4611       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4612       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4613       PetscFunctionReturn(PETSC_SUCCESS);
4614     }
4615     prev = next;
4616     next = next->next;
4617   }
4618   PetscCall(PetscNew(&prev->next));
4619   PetscCall(PetscStrallocpy(package, &prev->next->name));
4620   PetscCall(PetscNew(&prev->next->handlers));
4621   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4622   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4623   PetscFunctionReturn(PETSC_SUCCESS);
4624 }
4625 
4626 /*@C
4627   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4628 
4629   Input Parameters:
4630 + 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
4631 . ftype - the type of factorization supported by the type
4632 - mtype - the matrix type that works with this type
4633 
4634   Output Parameters:
4635 + foundtype    - `PETSC_TRUE` if the type was registered
4636 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4637 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4638 
4639   Calling sequence of `createfactor`:
4640 + A     - the matrix providing the factor matrix
4641 . ftype - the `MatFactorType` of the factor requested
4642 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4643 
4644   Level: developer
4645 
4646   Note:
4647   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4648   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4649   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4650 
4651 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4652           `MatInitializePackage()`
4653 @*/
4654 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4655 {
4656   MatSolverTypeHolder         next = MatSolverTypeHolders;
4657   PetscBool                   flg;
4658   MatSolverTypeForSpecifcType inext;
4659 
4660   PetscFunctionBegin;
4661   if (foundtype) *foundtype = PETSC_FALSE;
4662   if (foundmtype) *foundmtype = PETSC_FALSE;
4663   if (createfactor) *createfactor = NULL;
4664 
4665   if (type) {
4666     while (next) {
4667       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4668       if (flg) {
4669         if (foundtype) *foundtype = PETSC_TRUE;
4670         inext = next->handlers;
4671         while (inext) {
4672           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4673           if (flg) {
4674             if (foundmtype) *foundmtype = PETSC_TRUE;
4675             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4676             PetscFunctionReturn(PETSC_SUCCESS);
4677           }
4678           inext = inext->next;
4679         }
4680       }
4681       next = next->next;
4682     }
4683   } else {
4684     while (next) {
4685       inext = next->handlers;
4686       while (inext) {
4687         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4688         if (flg && inext->createfactor[(int)ftype - 1]) {
4689           if (foundtype) *foundtype = PETSC_TRUE;
4690           if (foundmtype) *foundmtype = PETSC_TRUE;
4691           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4692           PetscFunctionReturn(PETSC_SUCCESS);
4693         }
4694         inext = inext->next;
4695       }
4696       next = next->next;
4697     }
4698     /* try with base classes inext->mtype */
4699     next = MatSolverTypeHolders;
4700     while (next) {
4701       inext = next->handlers;
4702       while (inext) {
4703         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4704         if (flg && inext->createfactor[(int)ftype - 1]) {
4705           if (foundtype) *foundtype = PETSC_TRUE;
4706           if (foundmtype) *foundmtype = PETSC_TRUE;
4707           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4708           PetscFunctionReturn(PETSC_SUCCESS);
4709         }
4710         inext = inext->next;
4711       }
4712       next = next->next;
4713     }
4714   }
4715   PetscFunctionReturn(PETSC_SUCCESS);
4716 }
4717 
4718 PetscErrorCode MatSolverTypeDestroy(void)
4719 {
4720   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4721   MatSolverTypeForSpecifcType inext, iprev;
4722 
4723   PetscFunctionBegin;
4724   while (next) {
4725     PetscCall(PetscFree(next->name));
4726     inext = next->handlers;
4727     while (inext) {
4728       PetscCall(PetscFree(inext->mtype));
4729       iprev = inext;
4730       inext = inext->next;
4731       PetscCall(PetscFree(iprev));
4732     }
4733     prev = next;
4734     next = next->next;
4735     PetscCall(PetscFree(prev));
4736   }
4737   MatSolverTypeHolders = NULL;
4738   PetscFunctionReturn(PETSC_SUCCESS);
4739 }
4740 
4741 /*@
4742   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4743 
4744   Logically Collective
4745 
4746   Input Parameter:
4747 . mat - the matrix
4748 
4749   Output Parameter:
4750 . flg - `PETSC_TRUE` if uses the ordering
4751 
4752   Level: developer
4753 
4754   Note:
4755   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4756   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4757 
4758 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4759 @*/
4760 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4761 {
4762   PetscFunctionBegin;
4763   *flg = mat->canuseordering;
4764   PetscFunctionReturn(PETSC_SUCCESS);
4765 }
4766 
4767 /*@
4768   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4769 
4770   Logically Collective
4771 
4772   Input Parameters:
4773 + mat   - the matrix obtained with `MatGetFactor()`
4774 - ftype - the factorization type to be used
4775 
4776   Output Parameter:
4777 . otype - the preferred ordering type
4778 
4779   Level: developer
4780 
4781 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4782 @*/
4783 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4784 {
4785   PetscFunctionBegin;
4786   *otype = mat->preferredordering[ftype];
4787   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4788   PetscFunctionReturn(PETSC_SUCCESS);
4789 }
4790 
4791 /*@
4792   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4793 
4794   Collective
4795 
4796   Input Parameters:
4797 + mat   - the matrix
4798 . 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
4799           the other criteria is returned
4800 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4801 
4802   Output Parameter:
4803 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4804 
4805   Options Database Keys:
4806 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4807 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4808                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4809 
4810   Level: intermediate
4811 
4812   Notes:
4813   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4814   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4815 
4816   Users usually access the factorization solvers via `KSP`
4817 
4818   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4819   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
4820 
4821   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4822   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4823   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4824 
4825   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4826   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4827   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4828 
4829   Developer Note:
4830   This should actually be called `MatCreateFactor()` since it creates a new factor object
4831 
4832 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4833           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4834           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4835 @*/
4836 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4837 {
4838   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4839   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4840 
4841   PetscFunctionBegin;
4842   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4843   PetscValidType(mat, 1);
4844 
4845   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4846   MatCheckPreallocated(mat, 1);
4847 
4848   PetscCall(MatIsShell(mat, &shell));
4849   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4850   if (hasop) {
4851     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4852     PetscFunctionReturn(PETSC_SUCCESS);
4853   }
4854 
4855   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4856   if (!foundtype) {
4857     if (type) {
4858       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],
4859               ((PetscObject)mat)->type_name, type);
4860     } else {
4861       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);
4862     }
4863   }
4864   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4865   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);
4866 
4867   PetscCall((*conv)(mat, ftype, f));
4868   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4869   PetscFunctionReturn(PETSC_SUCCESS);
4870 }
4871 
4872 /*@
4873   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4874 
4875   Not Collective
4876 
4877   Input Parameters:
4878 + mat   - the matrix
4879 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4880 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4881 
4882   Output Parameter:
4883 . flg - PETSC_TRUE if the factorization is available
4884 
4885   Level: intermediate
4886 
4887   Notes:
4888   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4889   such as pastix, superlu, mumps etc.
4890 
4891   PETSc must have been ./configure to use the external solver, using the option --download-package
4892 
4893   Developer Note:
4894   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4895 
4896 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4897           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4898 @*/
4899 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4900 {
4901   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4902 
4903   PetscFunctionBegin;
4904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4905   PetscAssertPointer(flg, 4);
4906 
4907   *flg = PETSC_FALSE;
4908   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4909 
4910   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4911   MatCheckPreallocated(mat, 1);
4912 
4913   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4914   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4915   PetscFunctionReturn(PETSC_SUCCESS);
4916 }
4917 
4918 /*@
4919   MatDuplicate - Duplicates a matrix including the non-zero structure.
4920 
4921   Collective
4922 
4923   Input Parameters:
4924 + mat - the matrix
4925 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4926         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4927 
4928   Output Parameter:
4929 . M - pointer to place new matrix
4930 
4931   Level: intermediate
4932 
4933   Notes:
4934   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4935 
4936   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4937 
4938   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.
4939 
4940   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4941   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4942   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4943 
4944 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4945 @*/
4946 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4947 {
4948   Mat         B;
4949   VecType     vtype;
4950   PetscInt    i;
4951   PetscObject dm, container_h, container_d;
4952   void (*viewf)(void);
4953 
4954   PetscFunctionBegin;
4955   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4956   PetscValidType(mat, 1);
4957   PetscAssertPointer(M, 3);
4958   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4959   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4960   MatCheckPreallocated(mat, 1);
4961 
4962   *M = NULL;
4963   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4964   PetscUseTypeMethod(mat, duplicate, op, M);
4965   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4966   B = *M;
4967 
4968   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4969   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4970   PetscCall(MatGetVecType(mat, &vtype));
4971   PetscCall(MatSetVecType(B, vtype));
4972 
4973   B->stencil.dim = mat->stencil.dim;
4974   B->stencil.noc = mat->stencil.noc;
4975   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4976     B->stencil.dims[i]   = mat->stencil.dims[i];
4977     B->stencil.starts[i] = mat->stencil.starts[i];
4978   }
4979 
4980   B->nooffproczerorows = mat->nooffproczerorows;
4981   B->nooffprocentries  = mat->nooffprocentries;
4982 
4983   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4984   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4985   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4986   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4987   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4988   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4989   if (op == MAT_COPY_VALUES) PetscCall(MatPropagateSymmetryOptions(mat, B));
4990   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4991   PetscFunctionReturn(PETSC_SUCCESS);
4992 }
4993 
4994 /*@
4995   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4996 
4997   Logically Collective
4998 
4999   Input Parameter:
5000 . mat - the matrix
5001 
5002   Output Parameter:
5003 . v - the diagonal of the matrix
5004 
5005   Level: intermediate
5006 
5007   Note:
5008   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5009   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5010   is larger than `ndiag`, the values of the remaining entries are unspecified.
5011 
5012   Currently only correct in parallel for square matrices.
5013 
5014 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5015 @*/
5016 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5017 {
5018   PetscFunctionBegin;
5019   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5020   PetscValidType(mat, 1);
5021   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5022   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5023   MatCheckPreallocated(mat, 1);
5024   if (PetscDefined(USE_DEBUG)) {
5025     PetscInt nv, row, col, ndiag;
5026 
5027     PetscCall(VecGetLocalSize(v, &nv));
5028     PetscCall(MatGetLocalSize(mat, &row, &col));
5029     ndiag = PetscMin(row, col);
5030     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);
5031   }
5032 
5033   PetscUseTypeMethod(mat, getdiagonal, v);
5034   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5035   PetscFunctionReturn(PETSC_SUCCESS);
5036 }
5037 
5038 /*@
5039   MatGetRowMin - Gets the minimum value (of the real part) of each
5040   row of the matrix
5041 
5042   Logically Collective
5043 
5044   Input Parameter:
5045 . mat - the matrix
5046 
5047   Output Parameters:
5048 + v   - the vector for storing the maximums
5049 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5050 
5051   Level: intermediate
5052 
5053   Note:
5054   The result of this call are the same as if one converted the matrix to dense format
5055   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5056 
5057   This code is only implemented for a couple of matrix formats.
5058 
5059 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5060           `MatGetRowMax()`
5061 @*/
5062 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5063 {
5064   PetscFunctionBegin;
5065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5066   PetscValidType(mat, 1);
5067   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5068   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5069 
5070   if (!mat->cmap->N) {
5071     PetscCall(VecSet(v, PETSC_MAX_REAL));
5072     if (idx) {
5073       PetscInt i, m = mat->rmap->n;
5074       for (i = 0; i < m; i++) idx[i] = -1;
5075     }
5076   } else {
5077     MatCheckPreallocated(mat, 1);
5078   }
5079   PetscUseTypeMethod(mat, getrowmin, v, idx);
5080   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5081   PetscFunctionReturn(PETSC_SUCCESS);
5082 }
5083 
5084 /*@
5085   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5086   row of the matrix
5087 
5088   Logically Collective
5089 
5090   Input Parameter:
5091 . mat - the matrix
5092 
5093   Output Parameters:
5094 + v   - the vector for storing the minimums
5095 - idx - the indices of the column found for each row (or `NULL` if not needed)
5096 
5097   Level: intermediate
5098 
5099   Notes:
5100   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5101   row is 0 (the first column).
5102 
5103   This code is only implemented for a couple of matrix formats.
5104 
5105 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5106 @*/
5107 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5108 {
5109   PetscFunctionBegin;
5110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5111   PetscValidType(mat, 1);
5112   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5113   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5114   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5115 
5116   if (!mat->cmap->N) {
5117     PetscCall(VecSet(v, 0.0));
5118     if (idx) {
5119       PetscInt i, m = mat->rmap->n;
5120       for (i = 0; i < m; i++) idx[i] = -1;
5121     }
5122   } else {
5123     MatCheckPreallocated(mat, 1);
5124     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5125     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5126   }
5127   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5128   PetscFunctionReturn(PETSC_SUCCESS);
5129 }
5130 
5131 /*@
5132   MatGetRowMax - Gets the maximum value (of the real part) of each
5133   row of the matrix
5134 
5135   Logically Collective
5136 
5137   Input Parameter:
5138 . mat - the matrix
5139 
5140   Output Parameters:
5141 + v   - the vector for storing the maximums
5142 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5143 
5144   Level: intermediate
5145 
5146   Notes:
5147   The result of this call are the same as if one converted the matrix to dense format
5148   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5149 
5150   This code is only implemented for a couple of matrix formats.
5151 
5152 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5153 @*/
5154 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5155 {
5156   PetscFunctionBegin;
5157   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5158   PetscValidType(mat, 1);
5159   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5160   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5161 
5162   if (!mat->cmap->N) {
5163     PetscCall(VecSet(v, PETSC_MIN_REAL));
5164     if (idx) {
5165       PetscInt i, m = mat->rmap->n;
5166       for (i = 0; i < m; i++) idx[i] = -1;
5167     }
5168   } else {
5169     MatCheckPreallocated(mat, 1);
5170     PetscUseTypeMethod(mat, getrowmax, v, idx);
5171   }
5172   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5173   PetscFunctionReturn(PETSC_SUCCESS);
5174 }
5175 
5176 /*@
5177   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5178   row of the matrix
5179 
5180   Logically Collective
5181 
5182   Input Parameter:
5183 . mat - the matrix
5184 
5185   Output Parameters:
5186 + v   - the vector for storing the maximums
5187 - idx - the indices of the column found for each row (or `NULL` if not needed)
5188 
5189   Level: intermediate
5190 
5191   Notes:
5192   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5193   row is 0 (the first column).
5194 
5195   This code is only implemented for a couple of matrix formats.
5196 
5197 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5198 @*/
5199 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5200 {
5201   PetscFunctionBegin;
5202   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5203   PetscValidType(mat, 1);
5204   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5205   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5206 
5207   if (!mat->cmap->N) {
5208     PetscCall(VecSet(v, 0.0));
5209     if (idx) {
5210       PetscInt i, m = mat->rmap->n;
5211       for (i = 0; i < m; i++) idx[i] = -1;
5212     }
5213   } else {
5214     MatCheckPreallocated(mat, 1);
5215     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5216     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5217   }
5218   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5219   PetscFunctionReturn(PETSC_SUCCESS);
5220 }
5221 
5222 /*@
5223   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5224 
5225   Logically Collective
5226 
5227   Input Parameter:
5228 . mat - the matrix
5229 
5230   Output Parameter:
5231 . v - the vector for storing the sum
5232 
5233   Level: intermediate
5234 
5235   This code is only implemented for a couple of matrix formats.
5236 
5237 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5238 @*/
5239 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5240 {
5241   PetscFunctionBegin;
5242   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5243   PetscValidType(mat, 1);
5244   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5245   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5246 
5247   if (!mat->cmap->N) {
5248     PetscCall(VecSet(v, 0.0));
5249   } else {
5250     MatCheckPreallocated(mat, 1);
5251     PetscUseTypeMethod(mat, getrowsumabs, v);
5252   }
5253   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5254   PetscFunctionReturn(PETSC_SUCCESS);
5255 }
5256 
5257 /*@
5258   MatGetRowSum - Gets the sum of each row of the matrix
5259 
5260   Logically or Neighborhood Collective
5261 
5262   Input Parameter:
5263 . mat - the matrix
5264 
5265   Output Parameter:
5266 . v - the vector for storing the sum of rows
5267 
5268   Level: intermediate
5269 
5270   Note:
5271   This code is slow since it is not currently specialized for different formats
5272 
5273 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5274 @*/
5275 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5276 {
5277   Vec ones;
5278 
5279   PetscFunctionBegin;
5280   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5281   PetscValidType(mat, 1);
5282   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5283   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5284   MatCheckPreallocated(mat, 1);
5285   PetscCall(MatCreateVecs(mat, &ones, NULL));
5286   PetscCall(VecSet(ones, 1.));
5287   PetscCall(MatMult(mat, ones, v));
5288   PetscCall(VecDestroy(&ones));
5289   PetscFunctionReturn(PETSC_SUCCESS);
5290 }
5291 
5292 /*@
5293   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5294   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5295 
5296   Collective
5297 
5298   Input Parameter:
5299 . mat - the matrix to provide the transpose
5300 
5301   Output Parameter:
5302 . 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
5303 
5304   Level: advanced
5305 
5306   Note:
5307   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
5308   routine allows bypassing that call.
5309 
5310 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5311 @*/
5312 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5313 {
5314   PetscContainer  rB = NULL;
5315   MatParentState *rb = NULL;
5316 
5317   PetscFunctionBegin;
5318   PetscCall(PetscNew(&rb));
5319   rb->id    = ((PetscObject)mat)->id;
5320   rb->state = 0;
5321   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5322   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5323   PetscCall(PetscContainerSetPointer(rB, rb));
5324   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5325   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5326   PetscCall(PetscObjectDereference((PetscObject)rB));
5327   PetscFunctionReturn(PETSC_SUCCESS);
5328 }
5329 
5330 /*@
5331   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5332 
5333   Collective
5334 
5335   Input Parameters:
5336 + mat   - the matrix to transpose
5337 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5338 
5339   Output Parameter:
5340 . B - the transpose
5341 
5342   Level: intermediate
5343 
5344   Notes:
5345   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5346 
5347   `MAT_REUSE_MATRIX` uses the `B` matrix obtained from a previous call to this function with `MAT_INITIAL_MATRIX`. If you already have a matrix to contain the
5348   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5349 
5350   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.
5351 
5352   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5353 
5354   If mat is unchanged from the last call this function returns immediately without recomputing the result
5355 
5356   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5357 
5358 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5359           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5360 @*/
5361 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5362 {
5363   PetscContainer  rB = NULL;
5364   MatParentState *rb = NULL;
5365 
5366   PetscFunctionBegin;
5367   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5368   PetscValidType(mat, 1);
5369   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5370   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5371   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5372   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5373   MatCheckPreallocated(mat, 1);
5374   if (reuse == MAT_REUSE_MATRIX) {
5375     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5376     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5377     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5378     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5379     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5380   }
5381 
5382   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5383   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5384     PetscUseTypeMethod(mat, transpose, reuse, B);
5385     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5386   }
5387   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5388 
5389   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5390   if (reuse != MAT_INPLACE_MATRIX) {
5391     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5392     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5393     rb->state        = ((PetscObject)mat)->state;
5394     rb->nonzerostate = mat->nonzerostate;
5395   }
5396   PetscFunctionReturn(PETSC_SUCCESS);
5397 }
5398 
5399 /*@
5400   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5401 
5402   Collective
5403 
5404   Input Parameter:
5405 . A - the matrix to transpose
5406 
5407   Output Parameter:
5408 . 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
5409       numerical portion.
5410 
5411   Level: intermediate
5412 
5413   Note:
5414   This is not supported for many matrix types, use `MatTranspose()` in those cases
5415 
5416 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5417 @*/
5418 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5419 {
5420   PetscFunctionBegin;
5421   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5422   PetscValidType(A, 1);
5423   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5424   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5425   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5426   PetscUseTypeMethod(A, transposesymbolic, B);
5427   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5428 
5429   PetscCall(MatTransposeSetPrecursor(A, *B));
5430   PetscFunctionReturn(PETSC_SUCCESS);
5431 }
5432 
5433 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5434 {
5435   PetscContainer  rB;
5436   MatParentState *rb;
5437 
5438   PetscFunctionBegin;
5439   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5440   PetscValidType(A, 1);
5441   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5442   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5443   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5444   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5445   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5446   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5447   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5448   PetscFunctionReturn(PETSC_SUCCESS);
5449 }
5450 
5451 /*@
5452   MatIsTranspose - Test whether a matrix is another one's transpose,
5453   or its own, in which case it tests symmetry.
5454 
5455   Collective
5456 
5457   Input Parameters:
5458 + A   - the matrix to test
5459 . B   - the matrix to test against, this can equal the first parameter
5460 - tol - tolerance, differences between entries smaller than this are counted as zero
5461 
5462   Output Parameter:
5463 . flg - the result
5464 
5465   Level: intermediate
5466 
5467   Notes:
5468   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5469   test involves parallel copies of the block off-diagonal parts of the matrix.
5470 
5471 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5472 @*/
5473 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5474 {
5475   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5476 
5477   PetscFunctionBegin;
5478   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5479   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5480   PetscAssertPointer(flg, 4);
5481   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5482   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5483   *flg = PETSC_FALSE;
5484   if (f && g) {
5485     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5486     PetscCall((*f)(A, B, tol, flg));
5487   } else {
5488     MatType mattype;
5489 
5490     PetscCall(MatGetType(f ? B : A, &mattype));
5491     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5492   }
5493   PetscFunctionReturn(PETSC_SUCCESS);
5494 }
5495 
5496 /*@
5497   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5498 
5499   Collective
5500 
5501   Input Parameters:
5502 + mat   - the matrix to transpose and complex conjugate
5503 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5504 
5505   Output Parameter:
5506 . B - the Hermitian transpose
5507 
5508   Level: intermediate
5509 
5510 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5511 @*/
5512 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5513 {
5514   PetscFunctionBegin;
5515   PetscCall(MatTranspose(mat, reuse, B));
5516 #if defined(PETSC_USE_COMPLEX)
5517   PetscCall(MatConjugate(*B));
5518 #endif
5519   PetscFunctionReturn(PETSC_SUCCESS);
5520 }
5521 
5522 /*@
5523   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5524 
5525   Collective
5526 
5527   Input Parameters:
5528 + A   - the matrix to test
5529 . B   - the matrix to test against, this can equal the first parameter
5530 - tol - tolerance, differences between entries smaller than this are counted as zero
5531 
5532   Output Parameter:
5533 . flg - the result
5534 
5535   Level: intermediate
5536 
5537   Notes:
5538   Only available for `MATAIJ` matrices.
5539 
5540   The sequential algorithm
5541   has a running time of the order of the number of nonzeros; the parallel
5542   test involves parallel copies of the block off-diagonal parts of the matrix.
5543 
5544 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5545 @*/
5546 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5547 {
5548   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5549 
5550   PetscFunctionBegin;
5551   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5552   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5553   PetscAssertPointer(flg, 4);
5554   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5555   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5556   if (f && g) {
5557     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5558     PetscCall((*f)(A, B, tol, flg));
5559   }
5560   PetscFunctionReturn(PETSC_SUCCESS);
5561 }
5562 
5563 /*@
5564   MatPermute - Creates a new matrix with rows and columns permuted from the
5565   original.
5566 
5567   Collective
5568 
5569   Input Parameters:
5570 + mat - the matrix to permute
5571 . row - row permutation, each processor supplies only the permutation for its rows
5572 - col - column permutation, each processor supplies only the permutation for its columns
5573 
5574   Output Parameter:
5575 . B - the permuted matrix
5576 
5577   Level: advanced
5578 
5579   Note:
5580   The index sets map from row/col of permuted matrix to row/col of original matrix.
5581   The index sets should be on the same communicator as mat and have the same local sizes.
5582 
5583   Developer Note:
5584   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5585   exploit the fact that row and col are permutations, consider implementing the
5586   more general `MatCreateSubMatrix()` instead.
5587 
5588 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5589 @*/
5590 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5591 {
5592   PetscFunctionBegin;
5593   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5594   PetscValidType(mat, 1);
5595   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5596   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5597   PetscAssertPointer(B, 4);
5598   PetscCheckSameComm(mat, 1, row, 2);
5599   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5600   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5601   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5602   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5603   MatCheckPreallocated(mat, 1);
5604 
5605   if (mat->ops->permute) {
5606     PetscUseTypeMethod(mat, permute, row, col, B);
5607     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5608   } else {
5609     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5610   }
5611   PetscFunctionReturn(PETSC_SUCCESS);
5612 }
5613 
5614 /*@
5615   MatEqual - Compares two matrices.
5616 
5617   Collective
5618 
5619   Input Parameters:
5620 + A - the first matrix
5621 - B - the second matrix
5622 
5623   Output Parameter:
5624 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5625 
5626   Level: intermediate
5627 
5628 .seealso: [](ch_matrices), `Mat`
5629 @*/
5630 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5631 {
5632   PetscFunctionBegin;
5633   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5634   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5635   PetscValidType(A, 1);
5636   PetscValidType(B, 2);
5637   PetscAssertPointer(flg, 3);
5638   PetscCheckSameComm(A, 1, B, 2);
5639   MatCheckPreallocated(A, 1);
5640   MatCheckPreallocated(B, 2);
5641   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5642   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5643   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,
5644              B->cmap->N);
5645   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5646     PetscUseTypeMethod(A, equal, B, flg);
5647   } else {
5648     PetscCall(MatMultEqual(A, B, 10, flg));
5649   }
5650   PetscFunctionReturn(PETSC_SUCCESS);
5651 }
5652 
5653 /*@
5654   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5655   matrices that are stored as vectors.  Either of the two scaling
5656   matrices can be `NULL`.
5657 
5658   Collective
5659 
5660   Input Parameters:
5661 + mat - the matrix to be scaled
5662 . l   - the left scaling vector (or `NULL`)
5663 - r   - the right scaling vector (or `NULL`)
5664 
5665   Level: intermediate
5666 
5667   Note:
5668   `MatDiagonalScale()` computes $A = LAR$, where
5669   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5670   The L scales the rows of the matrix, the R scales the columns of the matrix.
5671 
5672 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5673 @*/
5674 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5675 {
5676   PetscFunctionBegin;
5677   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5678   PetscValidType(mat, 1);
5679   if (l) {
5680     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5681     PetscCheckSameComm(mat, 1, l, 2);
5682   }
5683   if (r) {
5684     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5685     PetscCheckSameComm(mat, 1, r, 3);
5686   }
5687   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5688   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5689   MatCheckPreallocated(mat, 1);
5690   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5691 
5692   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5693   PetscUseTypeMethod(mat, diagonalscale, l, r);
5694   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5695   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5696   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5697   PetscFunctionReturn(PETSC_SUCCESS);
5698 }
5699 
5700 /*@
5701   MatScale - Scales all elements of a matrix by a given number.
5702 
5703   Logically Collective
5704 
5705   Input Parameters:
5706 + mat - the matrix to be scaled
5707 - a   - the scaling value
5708 
5709   Level: intermediate
5710 
5711 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5712 @*/
5713 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5714 {
5715   PetscFunctionBegin;
5716   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5717   PetscValidType(mat, 1);
5718   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5719   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5720   PetscValidLogicalCollectiveScalar(mat, a, 2);
5721   MatCheckPreallocated(mat, 1);
5722 
5723   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5724   if (a != (PetscScalar)1.0) {
5725     PetscUseTypeMethod(mat, scale, a);
5726     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5727   }
5728   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5729   PetscFunctionReturn(PETSC_SUCCESS);
5730 }
5731 
5732 /*@
5733   MatNorm - Calculates various norms of a matrix.
5734 
5735   Collective
5736 
5737   Input Parameters:
5738 + mat  - the matrix
5739 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5740 
5741   Output Parameter:
5742 . nrm - the resulting norm
5743 
5744   Level: intermediate
5745 
5746 .seealso: [](ch_matrices), `Mat`
5747 @*/
5748 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5749 {
5750   PetscFunctionBegin;
5751   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5752   PetscValidType(mat, 1);
5753   PetscAssertPointer(nrm, 3);
5754 
5755   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5756   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5757   MatCheckPreallocated(mat, 1);
5758 
5759   PetscUseTypeMethod(mat, norm, type, nrm);
5760   PetscFunctionReturn(PETSC_SUCCESS);
5761 }
5762 
5763 /*
5764      This variable is used to prevent counting of MatAssemblyBegin() that
5765    are called from within a MatAssemblyEnd().
5766 */
5767 static PetscInt MatAssemblyEnd_InUse = 0;
5768 /*@
5769   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5770   be called after completing all calls to `MatSetValues()`.
5771 
5772   Collective
5773 
5774   Input Parameters:
5775 + mat  - the matrix
5776 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5777 
5778   Level: beginner
5779 
5780   Notes:
5781   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5782   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5783 
5784   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5785   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5786   using the matrix.
5787 
5788   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5789   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
5790   a global collective operation requiring all processes that share the matrix.
5791 
5792   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5793   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5794   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5795 
5796 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5797 @*/
5798 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5799 {
5800   PetscFunctionBegin;
5801   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5802   PetscValidType(mat, 1);
5803   MatCheckPreallocated(mat, 1);
5804   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5805   if (mat->assembled) {
5806     mat->was_assembled = PETSC_TRUE;
5807     mat->assembled     = PETSC_FALSE;
5808   }
5809 
5810   if (!MatAssemblyEnd_InUse) {
5811     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5812     PetscTryTypeMethod(mat, assemblybegin, type);
5813     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5814   } else PetscTryTypeMethod(mat, assemblybegin, type);
5815   PetscFunctionReturn(PETSC_SUCCESS);
5816 }
5817 
5818 /*@
5819   MatAssembled - Indicates if a matrix has been assembled and is ready for
5820   use; for example, in matrix-vector product.
5821 
5822   Not Collective
5823 
5824   Input Parameter:
5825 . mat - the matrix
5826 
5827   Output Parameter:
5828 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5829 
5830   Level: advanced
5831 
5832 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5833 @*/
5834 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5835 {
5836   PetscFunctionBegin;
5837   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5838   PetscAssertPointer(assembled, 2);
5839   *assembled = mat->assembled;
5840   PetscFunctionReturn(PETSC_SUCCESS);
5841 }
5842 
5843 /*@
5844   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5845   be called after `MatAssemblyBegin()`.
5846 
5847   Collective
5848 
5849   Input Parameters:
5850 + mat  - the matrix
5851 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5852 
5853   Options Database Keys:
5854 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5855 . -mat_view ::ascii_info_detail      - Prints more detailed info
5856 . -mat_view                          - Prints matrix in ASCII format
5857 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5858 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5859 . -display <name>                    - Sets display name (default is host)
5860 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5861 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5862 . -viewer_socket_machine <machine>   - Machine to use for socket
5863 . -viewer_socket_port <port>         - Port number to use for socket
5864 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5865 
5866   Level: beginner
5867 
5868 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5869 @*/
5870 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5871 {
5872   static PetscInt inassm = 0;
5873   PetscBool       flg    = PETSC_FALSE;
5874 
5875   PetscFunctionBegin;
5876   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5877   PetscValidType(mat, 1);
5878 
5879   inassm++;
5880   MatAssemblyEnd_InUse++;
5881   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5882     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5883     PetscTryTypeMethod(mat, assemblyend, type);
5884     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5885   } else PetscTryTypeMethod(mat, assemblyend, type);
5886 
5887   /* Flush assembly is not a true assembly */
5888   if (type != MAT_FLUSH_ASSEMBLY) {
5889     if (mat->num_ass) {
5890       if (!mat->symmetry_eternal) {
5891         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5892         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5893       }
5894       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5895       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5896     }
5897     mat->num_ass++;
5898     mat->assembled        = PETSC_TRUE;
5899     mat->ass_nonzerostate = mat->nonzerostate;
5900   }
5901 
5902   mat->insertmode = NOT_SET_VALUES;
5903   MatAssemblyEnd_InUse--;
5904   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5905   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5906     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5907 
5908     if (mat->checksymmetryonassembly) {
5909       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5910       if (flg) {
5911         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5912       } else {
5913         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5914       }
5915     }
5916     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5917   }
5918   inassm--;
5919   PetscFunctionReturn(PETSC_SUCCESS);
5920 }
5921 
5922 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5923 /*@
5924   MatSetOption - Sets a parameter option for a matrix. Some options
5925   may be specific to certain storage formats.  Some options
5926   determine how values will be inserted (or added). Sorted,
5927   row-oriented input will generally assemble the fastest. The default
5928   is row-oriented.
5929 
5930   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5931 
5932   Input Parameters:
5933 + mat - the matrix
5934 . op  - the option, one of those listed below (and possibly others),
5935 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5936 
5937   Options Describing Matrix Structure:
5938 + `MAT_SPD`                         - symmetric positive definite
5939 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5940 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5941 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5942 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5943 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5944 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5945 
5946    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5947    do not need to be computed (usually at a high cost)
5948 
5949    Options For Use with `MatSetValues()`:
5950    Insert a logically dense subblock, which can be
5951 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5952 
5953    These options reflect the data you pass in with `MatSetValues()`; it has
5954    nothing to do with how the data is stored internally in the matrix
5955    data structure.
5956 
5957    When (re)assembling a matrix, we can restrict the input for
5958    efficiency/debugging purposes.  These options include
5959 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5960 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5961 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5962 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5963 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5964 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5965         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5966         performance for very large process counts.
5967 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5968         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5969         functions, instead sending only neighbor messages.
5970 
5971   Level: intermediate
5972 
5973   Notes:
5974   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5975 
5976   Some options are relevant only for particular matrix types and
5977   are thus ignored by others.  Other options are not supported by
5978   certain matrix types and will generate an error message if set.
5979 
5980   If using Fortran to compute a matrix, one may need to
5981   use the column-oriented option (or convert to the row-oriented
5982   format).
5983 
5984   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5985   that would generate a new entry in the nonzero structure is instead
5986   ignored.  Thus, if memory has not already been allocated for this particular
5987   data, then the insertion is ignored. For dense matrices, in which
5988   the entire array is allocated, no entries are ever ignored.
5989   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5990 
5991   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5992   that would generate a new entry in the nonzero structure instead produces
5993   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
5994 
5995   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5996   that would generate a new entry that has not been preallocated will
5997   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5998   only.) This is a useful flag when debugging matrix memory preallocation.
5999   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
6000 
6001   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
6002   other processors should be dropped, rather than stashed.
6003   This is useful if you know that the "owning" processor is also
6004   always generating the correct matrix entries, so that PETSc need
6005   not transfer duplicate entries generated on another processor.
6006 
6007   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6008   searches during matrix assembly. When this flag is set, the hash table
6009   is created during the first matrix assembly. This hash table is
6010   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6011   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6012   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6013   supported by `MATMPIBAIJ` format only.
6014 
6015   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6016   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6017 
6018   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6019   a zero location in the matrix
6020 
6021   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6022 
6023   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6024   zero row routines and thus improves performance for very large process counts.
6025 
6026   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6027   part of the matrix (since they should match the upper triangular part).
6028 
6029   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6030   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6031   with finite difference schemes with non-periodic boundary conditions.
6032 
6033   Developer Note:
6034   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6035   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6036   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6037   not changed.
6038 
6039 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6040 @*/
6041 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6042 {
6043   PetscFunctionBegin;
6044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6045   if (op > 0) {
6046     PetscValidLogicalCollectiveEnum(mat, op, 2);
6047     PetscValidLogicalCollectiveBool(mat, flg, 3);
6048   }
6049 
6050   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);
6051 
6052   switch (op) {
6053   case MAT_FORCE_DIAGONAL_ENTRIES:
6054     mat->force_diagonals = flg;
6055     PetscFunctionReturn(PETSC_SUCCESS);
6056   case MAT_NO_OFF_PROC_ENTRIES:
6057     mat->nooffprocentries = flg;
6058     PetscFunctionReturn(PETSC_SUCCESS);
6059   case MAT_SUBSET_OFF_PROC_ENTRIES:
6060     mat->assembly_subset = flg;
6061     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6062 #if !defined(PETSC_HAVE_MPIUNI)
6063       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6064 #endif
6065       mat->stash.first_assembly_done = PETSC_FALSE;
6066     }
6067     PetscFunctionReturn(PETSC_SUCCESS);
6068   case MAT_NO_OFF_PROC_ZERO_ROWS:
6069     mat->nooffproczerorows = flg;
6070     PetscFunctionReturn(PETSC_SUCCESS);
6071   case MAT_SPD:
6072     if (flg) {
6073       mat->spd                    = PETSC_BOOL3_TRUE;
6074       mat->symmetric              = PETSC_BOOL3_TRUE;
6075       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6076     } else {
6077       mat->spd = PETSC_BOOL3_FALSE;
6078     }
6079     break;
6080   case MAT_SYMMETRIC:
6081     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6082     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6083 #if !defined(PETSC_USE_COMPLEX)
6084     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6085 #endif
6086     break;
6087   case MAT_HERMITIAN:
6088     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6089     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6090 #if !defined(PETSC_USE_COMPLEX)
6091     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6092 #endif
6093     break;
6094   case MAT_STRUCTURALLY_SYMMETRIC:
6095     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6096     break;
6097   case MAT_SYMMETRY_ETERNAL:
6098     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");
6099     mat->symmetry_eternal = flg;
6100     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6101     break;
6102   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6103     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");
6104     mat->structural_symmetry_eternal = flg;
6105     break;
6106   case MAT_SPD_ETERNAL:
6107     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");
6108     mat->spd_eternal = flg;
6109     if (flg) {
6110       mat->structural_symmetry_eternal = PETSC_TRUE;
6111       mat->symmetry_eternal            = PETSC_TRUE;
6112     }
6113     break;
6114   case MAT_STRUCTURE_ONLY:
6115     mat->structure_only = flg;
6116     break;
6117   case MAT_SORTED_FULL:
6118     mat->sortedfull = flg;
6119     break;
6120   default:
6121     break;
6122   }
6123   PetscTryTypeMethod(mat, setoption, op, flg);
6124   PetscFunctionReturn(PETSC_SUCCESS);
6125 }
6126 
6127 /*@
6128   MatGetOption - Gets a parameter option that has been set for a matrix.
6129 
6130   Logically Collective
6131 
6132   Input Parameters:
6133 + mat - the matrix
6134 - op  - the option, this only responds to certain options, check the code for which ones
6135 
6136   Output Parameter:
6137 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6138 
6139   Level: intermediate
6140 
6141   Notes:
6142   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6143 
6144   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6145   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6146 
6147 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6148     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6149 @*/
6150 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6151 {
6152   PetscFunctionBegin;
6153   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6154   PetscValidType(mat, 1);
6155 
6156   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);
6157   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()");
6158 
6159   switch (op) {
6160   case MAT_NO_OFF_PROC_ENTRIES:
6161     *flg = mat->nooffprocentries;
6162     break;
6163   case MAT_NO_OFF_PROC_ZERO_ROWS:
6164     *flg = mat->nooffproczerorows;
6165     break;
6166   case MAT_SYMMETRIC:
6167     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6168     break;
6169   case MAT_HERMITIAN:
6170     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6171     break;
6172   case MAT_STRUCTURALLY_SYMMETRIC:
6173     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6174     break;
6175   case MAT_SPD:
6176     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6177     break;
6178   case MAT_SYMMETRY_ETERNAL:
6179     *flg = mat->symmetry_eternal;
6180     break;
6181   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6182     *flg = mat->symmetry_eternal;
6183     break;
6184   default:
6185     break;
6186   }
6187   PetscFunctionReturn(PETSC_SUCCESS);
6188 }
6189 
6190 /*@
6191   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6192   this routine retains the old nonzero structure.
6193 
6194   Logically Collective
6195 
6196   Input Parameter:
6197 . mat - the matrix
6198 
6199   Level: intermediate
6200 
6201   Note:
6202   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.
6203   See the Performance chapter of the users manual for information on preallocating matrices.
6204 
6205 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6206 @*/
6207 PetscErrorCode MatZeroEntries(Mat mat)
6208 {
6209   PetscFunctionBegin;
6210   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6211   PetscValidType(mat, 1);
6212   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6213   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");
6214   MatCheckPreallocated(mat, 1);
6215 
6216   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6217   PetscUseTypeMethod(mat, zeroentries);
6218   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6219   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6220   PetscFunctionReturn(PETSC_SUCCESS);
6221 }
6222 
6223 /*@
6224   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6225   of a set of rows and columns of a matrix.
6226 
6227   Collective
6228 
6229   Input Parameters:
6230 + mat     - the matrix
6231 . numRows - the number of rows/columns to zero
6232 . rows    - the global row indices
6233 . diag    - value put in the diagonal of the eliminated rows
6234 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6235 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6236 
6237   Level: intermediate
6238 
6239   Notes:
6240   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6241 
6242   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6243   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
6244 
6245   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6246   Krylov method to take advantage of the known solution on the zeroed rows.
6247 
6248   For the parallel case, all processes that share the matrix (i.e.,
6249   those in the communicator used for matrix creation) MUST call this
6250   routine, regardless of whether any rows being zeroed are owned by
6251   them.
6252 
6253   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6254   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
6255   missing.
6256 
6257   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6258   list only rows local to itself).
6259 
6260   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6261 
6262 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6263           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6264 @*/
6265 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6266 {
6267   PetscFunctionBegin;
6268   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6269   PetscValidType(mat, 1);
6270   if (numRows) PetscAssertPointer(rows, 3);
6271   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6272   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6273   MatCheckPreallocated(mat, 1);
6274 
6275   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6276   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6277   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6278   PetscFunctionReturn(PETSC_SUCCESS);
6279 }
6280 
6281 /*@
6282   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6283   of a set of rows and columns of a matrix.
6284 
6285   Collective
6286 
6287   Input Parameters:
6288 + mat  - the matrix
6289 . is   - the rows to zero
6290 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6291 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6292 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6293 
6294   Level: intermediate
6295 
6296   Note:
6297   See `MatZeroRowsColumns()` for details on how this routine operates.
6298 
6299 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6300           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6301 @*/
6302 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6303 {
6304   PetscInt        numRows;
6305   const PetscInt *rows;
6306 
6307   PetscFunctionBegin;
6308   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6309   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6310   PetscValidType(mat, 1);
6311   PetscValidType(is, 2);
6312   PetscCall(ISGetLocalSize(is, &numRows));
6313   PetscCall(ISGetIndices(is, &rows));
6314   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6315   PetscCall(ISRestoreIndices(is, &rows));
6316   PetscFunctionReturn(PETSC_SUCCESS);
6317 }
6318 
6319 /*@
6320   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6321   of a set of rows of a matrix.
6322 
6323   Collective
6324 
6325   Input Parameters:
6326 + mat     - the matrix
6327 . numRows - the number of rows to zero
6328 . rows    - the global row indices
6329 . diag    - value put in the diagonal of the zeroed rows
6330 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6331 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6332 
6333   Level: intermediate
6334 
6335   Notes:
6336   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6337 
6338   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6339 
6340   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6341   Krylov method to take advantage of the known solution on the zeroed rows.
6342 
6343   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)
6344   from the matrix.
6345 
6346   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6347   but does not release memory.  Because of this removal matrix-vector products with the adjusted matrix will be a bit faster. For the dense and block diagonal
6348   formats this does not alter the nonzero structure.
6349 
6350   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6351   of the matrix is not changed the values are
6352   merely zeroed.
6353 
6354   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6355   formats can optionally remove the main diagonal entry from the
6356   nonzero structure as well, by passing 0.0 as the final argument).
6357 
6358   For the parallel case, all processes that share the matrix (i.e.,
6359   those in the communicator used for matrix creation) MUST call this
6360   routine, regardless of whether any rows being zeroed are owned by
6361   them.
6362 
6363   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6364   list only rows local to itself).
6365 
6366   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6367   owns that are to be zeroed. This saves a global synchronization in the implementation.
6368 
6369 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6370           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6371 @*/
6372 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6373 {
6374   PetscFunctionBegin;
6375   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6376   PetscValidType(mat, 1);
6377   if (numRows) PetscAssertPointer(rows, 3);
6378   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6379   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6380   MatCheckPreallocated(mat, 1);
6381 
6382   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6383   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6384   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6385   PetscFunctionReturn(PETSC_SUCCESS);
6386 }
6387 
6388 /*@
6389   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6390   of a set of rows of a matrix.
6391 
6392   Collective
6393 
6394   Input Parameters:
6395 + mat  - the matrix
6396 . is   - index set of rows to remove (if `NULL` then no row is removed)
6397 . diag - value put in all diagonals of eliminated rows
6398 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6399 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6400 
6401   Level: intermediate
6402 
6403   Note:
6404   See `MatZeroRows()` for details on how this routine operates.
6405 
6406 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6407           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6408 @*/
6409 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6410 {
6411   PetscInt        numRows = 0;
6412   const PetscInt *rows    = NULL;
6413 
6414   PetscFunctionBegin;
6415   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6416   PetscValidType(mat, 1);
6417   if (is) {
6418     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6419     PetscCall(ISGetLocalSize(is, &numRows));
6420     PetscCall(ISGetIndices(is, &rows));
6421   }
6422   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6423   if (is) PetscCall(ISRestoreIndices(is, &rows));
6424   PetscFunctionReturn(PETSC_SUCCESS);
6425 }
6426 
6427 /*@
6428   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6429   of a set of rows of a matrix. These rows must be local to the process.
6430 
6431   Collective
6432 
6433   Input Parameters:
6434 + mat     - the matrix
6435 . numRows - the number of rows to remove
6436 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6437 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6438 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6439 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6440 
6441   Level: intermediate
6442 
6443   Notes:
6444   See `MatZeroRows()` for details on how this routine operates.
6445 
6446   The grid coordinates are across the entire grid, not just the local portion
6447 
6448   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6449   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6450   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6451   `DM_BOUNDARY_PERIODIC` boundary type.
6452 
6453   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
6454   a single value per point) you can skip filling those indices.
6455 
6456   Fortran Note:
6457   `idxm` and `idxn` should be declared as
6458 $     MatStencil idxm(4, m)
6459   and the values inserted using
6460 .vb
6461     idxm(MatStencil_i, 1) = i
6462     idxm(MatStencil_j, 1) = j
6463     idxm(MatStencil_k, 1) = k
6464     idxm(MatStencil_c, 1) = c
6465    etc
6466 .ve
6467 
6468 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRows()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6469           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6470 @*/
6471 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6472 {
6473   PetscInt  dim    = mat->stencil.dim;
6474   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6475   PetscInt *dims   = mat->stencil.dims + 1;
6476   PetscInt *starts = mat->stencil.starts;
6477   PetscInt *dxm    = (PetscInt *)rows;
6478   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6479 
6480   PetscFunctionBegin;
6481   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6482   PetscValidType(mat, 1);
6483   if (numRows) PetscAssertPointer(rows, 3);
6484 
6485   PetscCall(PetscMalloc1(numRows, &jdxm));
6486   for (i = 0; i < numRows; ++i) {
6487     /* Skip unused dimensions (they are ordered k, j, i, c) */
6488     for (j = 0; j < 3 - sdim; ++j) dxm++;
6489     /* Local index in X dir */
6490     tmp = *dxm++ - starts[0];
6491     /* Loop over remaining dimensions */
6492     for (j = 0; j < dim - 1; ++j) {
6493       /* If nonlocal, set index to be negative */
6494       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6495       /* Update local index */
6496       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6497     }
6498     /* Skip component slot if necessary */
6499     if (mat->stencil.noc) dxm++;
6500     /* Local row number */
6501     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6502   }
6503   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6504   PetscCall(PetscFree(jdxm));
6505   PetscFunctionReturn(PETSC_SUCCESS);
6506 }
6507 
6508 /*@
6509   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6510   of a set of rows and columns of a matrix.
6511 
6512   Collective
6513 
6514   Input Parameters:
6515 + mat     - the matrix
6516 . numRows - the number of rows/columns to remove
6517 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6518 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6519 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6520 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6521 
6522   Level: intermediate
6523 
6524   Notes:
6525   See `MatZeroRowsColumns()` for details on how this routine operates.
6526 
6527   The grid coordinates are across the entire grid, not just the local portion
6528 
6529   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6530   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6531   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6532   `DM_BOUNDARY_PERIODIC` boundary type.
6533 
6534   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
6535   a single value per point) you can skip filling those indices.
6536 
6537   Fortran Note:
6538   `idxm` and `idxn` should be declared as
6539 $     MatStencil idxm(4, m)
6540   and the values inserted using
6541 .vb
6542     idxm(MatStencil_i, 1) = i
6543     idxm(MatStencil_j, 1) = j
6544     idxm(MatStencil_k, 1) = k
6545     idxm(MatStencil_c, 1) = c
6546     etc
6547 .ve
6548 
6549 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6550           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6551 @*/
6552 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6553 {
6554   PetscInt  dim    = mat->stencil.dim;
6555   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6556   PetscInt *dims   = mat->stencil.dims + 1;
6557   PetscInt *starts = mat->stencil.starts;
6558   PetscInt *dxm    = (PetscInt *)rows;
6559   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6560 
6561   PetscFunctionBegin;
6562   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6563   PetscValidType(mat, 1);
6564   if (numRows) PetscAssertPointer(rows, 3);
6565 
6566   PetscCall(PetscMalloc1(numRows, &jdxm));
6567   for (i = 0; i < numRows; ++i) {
6568     /* Skip unused dimensions (they are ordered k, j, i, c) */
6569     for (j = 0; j < 3 - sdim; ++j) dxm++;
6570     /* Local index in X dir */
6571     tmp = *dxm++ - starts[0];
6572     /* Loop over remaining dimensions */
6573     for (j = 0; j < dim - 1; ++j) {
6574       /* If nonlocal, set index to be negative */
6575       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6576       /* Update local index */
6577       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6578     }
6579     /* Skip component slot if necessary */
6580     if (mat->stencil.noc) dxm++;
6581     /* Local row number */
6582     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6583   }
6584   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6585   PetscCall(PetscFree(jdxm));
6586   PetscFunctionReturn(PETSC_SUCCESS);
6587 }
6588 
6589 /*@
6590   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6591   of a set of rows of a matrix; using local numbering of rows.
6592 
6593   Collective
6594 
6595   Input Parameters:
6596 + mat     - the matrix
6597 . numRows - the number of rows to remove
6598 . rows    - the local row indices
6599 . diag    - value put in all diagonals of eliminated rows
6600 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6601 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6602 
6603   Level: intermediate
6604 
6605   Notes:
6606   Before calling `MatZeroRowsLocal()`, the user must first set the
6607   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6608 
6609   See `MatZeroRows()` for details on how this routine operates.
6610 
6611 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6612           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6613 @*/
6614 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6615 {
6616   PetscFunctionBegin;
6617   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6618   PetscValidType(mat, 1);
6619   if (numRows) PetscAssertPointer(rows, 3);
6620   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6621   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6622   MatCheckPreallocated(mat, 1);
6623 
6624   if (mat->ops->zerorowslocal) {
6625     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6626   } else {
6627     IS              is, newis;
6628     const PetscInt *newRows;
6629 
6630     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6631     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6632     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6633     PetscCall(ISGetIndices(newis, &newRows));
6634     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6635     PetscCall(ISRestoreIndices(newis, &newRows));
6636     PetscCall(ISDestroy(&newis));
6637     PetscCall(ISDestroy(&is));
6638   }
6639   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6640   PetscFunctionReturn(PETSC_SUCCESS);
6641 }
6642 
6643 /*@
6644   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6645   of a set of rows of a matrix; using local numbering of rows.
6646 
6647   Collective
6648 
6649   Input Parameters:
6650 + mat  - the matrix
6651 . is   - index set of rows to remove
6652 . diag - value put in all diagonals of eliminated rows
6653 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6654 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6655 
6656   Level: intermediate
6657 
6658   Notes:
6659   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6660   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6661 
6662   See `MatZeroRows()` for details on how this routine operates.
6663 
6664 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6665           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6666 @*/
6667 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6668 {
6669   PetscInt        numRows;
6670   const PetscInt *rows;
6671 
6672   PetscFunctionBegin;
6673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6674   PetscValidType(mat, 1);
6675   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6676   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6677   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6678   MatCheckPreallocated(mat, 1);
6679 
6680   PetscCall(ISGetLocalSize(is, &numRows));
6681   PetscCall(ISGetIndices(is, &rows));
6682   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6683   PetscCall(ISRestoreIndices(is, &rows));
6684   PetscFunctionReturn(PETSC_SUCCESS);
6685 }
6686 
6687 /*@
6688   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6689   of a set of rows and columns of a matrix; using local numbering of rows.
6690 
6691   Collective
6692 
6693   Input Parameters:
6694 + mat     - the matrix
6695 . numRows - the number of rows to remove
6696 . rows    - the global row indices
6697 . diag    - value put in all diagonals of eliminated rows
6698 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6699 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6700 
6701   Level: intermediate
6702 
6703   Notes:
6704   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6705   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6706 
6707   See `MatZeroRowsColumns()` for details on how this routine operates.
6708 
6709 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6710           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6711 @*/
6712 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6713 {
6714   IS              is, newis;
6715   const PetscInt *newRows;
6716 
6717   PetscFunctionBegin;
6718   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6719   PetscValidType(mat, 1);
6720   if (numRows) PetscAssertPointer(rows, 3);
6721   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6722   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6723   MatCheckPreallocated(mat, 1);
6724 
6725   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6726   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6727   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6728   PetscCall(ISGetIndices(newis, &newRows));
6729   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6730   PetscCall(ISRestoreIndices(newis, &newRows));
6731   PetscCall(ISDestroy(&newis));
6732   PetscCall(ISDestroy(&is));
6733   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6734   PetscFunctionReturn(PETSC_SUCCESS);
6735 }
6736 
6737 /*@
6738   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6739   of a set of rows and columns of a matrix; using local numbering of rows.
6740 
6741   Collective
6742 
6743   Input Parameters:
6744 + mat  - the matrix
6745 . is   - index set of rows to remove
6746 . diag - value put in all diagonals of eliminated rows
6747 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6748 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6749 
6750   Level: intermediate
6751 
6752   Notes:
6753   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6754   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6755 
6756   See `MatZeroRowsColumns()` for details on how this routine operates.
6757 
6758 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6759           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6760 @*/
6761 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6762 {
6763   PetscInt        numRows;
6764   const PetscInt *rows;
6765 
6766   PetscFunctionBegin;
6767   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6768   PetscValidType(mat, 1);
6769   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6770   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6771   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6772   MatCheckPreallocated(mat, 1);
6773 
6774   PetscCall(ISGetLocalSize(is, &numRows));
6775   PetscCall(ISGetIndices(is, &rows));
6776   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6777   PetscCall(ISRestoreIndices(is, &rows));
6778   PetscFunctionReturn(PETSC_SUCCESS);
6779 }
6780 
6781 /*@
6782   MatGetSize - Returns the numbers of rows and columns in a matrix.
6783 
6784   Not Collective
6785 
6786   Input Parameter:
6787 . mat - the matrix
6788 
6789   Output Parameters:
6790 + m - the number of global rows
6791 - n - the number of global columns
6792 
6793   Level: beginner
6794 
6795   Note:
6796   Both output parameters can be `NULL` on input.
6797 
6798 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6799 @*/
6800 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6801 {
6802   PetscFunctionBegin;
6803   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6804   if (m) *m = mat->rmap->N;
6805   if (n) *n = mat->cmap->N;
6806   PetscFunctionReturn(PETSC_SUCCESS);
6807 }
6808 
6809 /*@
6810   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6811   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6812 
6813   Not Collective
6814 
6815   Input Parameter:
6816 . mat - the matrix
6817 
6818   Output Parameters:
6819 + m - the number of local rows, use `NULL` to not obtain this value
6820 - n - the number of local columns, use `NULL` to not obtain this value
6821 
6822   Level: beginner
6823 
6824 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6825 @*/
6826 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6827 {
6828   PetscFunctionBegin;
6829   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6830   if (m) PetscAssertPointer(m, 2);
6831   if (n) PetscAssertPointer(n, 3);
6832   if (m) *m = mat->rmap->n;
6833   if (n) *n = mat->cmap->n;
6834   PetscFunctionReturn(PETSC_SUCCESS);
6835 }
6836 
6837 /*@
6838   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6839   vector one multiplies this matrix by that are owned by this processor.
6840 
6841   Not Collective, unless matrix has not been allocated, then collective
6842 
6843   Input Parameter:
6844 . mat - the matrix
6845 
6846   Output Parameters:
6847 + m - the global index of the first local column, use `NULL` to not obtain this value
6848 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6849 
6850   Level: developer
6851 
6852   Notes:
6853   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6854 
6855   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6856   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6857 
6858   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6859   the local values in the matrix.
6860 
6861   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6862   Layouts](sec_matlayout) for details on matrix layouts.
6863 
6864 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6865           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6866 @*/
6867 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6868 {
6869   PetscFunctionBegin;
6870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6871   PetscValidType(mat, 1);
6872   if (m) PetscAssertPointer(m, 2);
6873   if (n) PetscAssertPointer(n, 3);
6874   MatCheckPreallocated(mat, 1);
6875   if (m) *m = mat->cmap->rstart;
6876   if (n) *n = mat->cmap->rend;
6877   PetscFunctionReturn(PETSC_SUCCESS);
6878 }
6879 
6880 /*@
6881   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6882   this MPI process.
6883 
6884   Not Collective
6885 
6886   Input Parameter:
6887 . mat - the matrix
6888 
6889   Output Parameters:
6890 + m - the global index of the first local row, use `NULL` to not obtain this value
6891 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6892 
6893   Level: beginner
6894 
6895   Notes:
6896   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6897 
6898   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6899   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6900 
6901   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6902   the local values in the matrix.
6903 
6904   The high argument is one more than the last element stored locally.
6905 
6906   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6907   would contain the result of a matrix vector product with this matrix. See [Matrix
6908   Layouts](sec_matlayout) for details on matrix layouts.
6909 
6910 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6911           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6912 @*/
6913 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6914 {
6915   PetscFunctionBegin;
6916   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6917   PetscValidType(mat, 1);
6918   if (m) PetscAssertPointer(m, 2);
6919   if (n) PetscAssertPointer(n, 3);
6920   MatCheckPreallocated(mat, 1);
6921   if (m) *m = mat->rmap->rstart;
6922   if (n) *n = mat->rmap->rend;
6923   PetscFunctionReturn(PETSC_SUCCESS);
6924 }
6925 
6926 /*@C
6927   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6928   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6929 
6930   Not Collective, unless matrix has not been allocated
6931 
6932   Input Parameter:
6933 . mat - the matrix
6934 
6935   Output Parameter:
6936 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6937            where `size` is the number of MPI processes used by `mat`
6938 
6939   Level: beginner
6940 
6941   Notes:
6942   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6943 
6944   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6945   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6946 
6947   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6948   the local values in the matrix.
6949 
6950   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6951   would contain the result of a matrix vector product with this matrix. See [Matrix
6952   Layouts](sec_matlayout) for details on matrix layouts.
6953 
6954 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6955           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6956           `DMDAGetGhostCorners()`, `DM`
6957 @*/
6958 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6959 {
6960   PetscFunctionBegin;
6961   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6962   PetscValidType(mat, 1);
6963   MatCheckPreallocated(mat, 1);
6964   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6965   PetscFunctionReturn(PETSC_SUCCESS);
6966 }
6967 
6968 /*@C
6969   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6970   vector one multiplies this vector by that are owned by each processor.
6971 
6972   Not Collective, unless matrix has not been allocated
6973 
6974   Input Parameter:
6975 . mat - the matrix
6976 
6977   Output Parameter:
6978 . ranges - start of each processors portion plus one more than the total length at the end
6979 
6980   Level: beginner
6981 
6982   Notes:
6983   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6984 
6985   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6986   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6987 
6988   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6989   the local values in the matrix.
6990 
6991   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6992   Layouts](sec_matlayout) for details on matrix layouts.
6993 
6994 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
6995           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
6996           `DMDAGetGhostCorners()`, `DM`
6997 @*/
6998 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
6999 {
7000   PetscFunctionBegin;
7001   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7002   PetscValidType(mat, 1);
7003   MatCheckPreallocated(mat, 1);
7004   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7005   PetscFunctionReturn(PETSC_SUCCESS);
7006 }
7007 
7008 /*@
7009   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7010 
7011   Not Collective
7012 
7013   Input Parameter:
7014 . A - matrix
7015 
7016   Output Parameters:
7017 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7018 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7019 
7020   Level: intermediate
7021 
7022   Note:
7023   You should call `ISDestroy()` on the returned `IS`
7024 
7025   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7026   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7027   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7028   details on matrix layouts.
7029 
7030 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7031 @*/
7032 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7033 {
7034   PetscErrorCode (*f)(Mat, IS *, IS *);
7035 
7036   PetscFunctionBegin;
7037   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7038   PetscValidType(A, 1);
7039   MatCheckPreallocated(A, 1);
7040   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7041   if (f) {
7042     PetscCall((*f)(A, rows, cols));
7043   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7044     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7045     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7046   }
7047   PetscFunctionReturn(PETSC_SUCCESS);
7048 }
7049 
7050 /*@
7051   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7052   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7053   to complete the factorization.
7054 
7055   Collective
7056 
7057   Input Parameters:
7058 + fact - the factorized matrix obtained with `MatGetFactor()`
7059 . mat  - the matrix
7060 . row  - row permutation
7061 . col  - column permutation
7062 - info - structure containing
7063 .vb
7064       levels - number of levels of fill.
7065       expected fill - as ratio of original fill.
7066       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7067                 missing diagonal entries)
7068 .ve
7069 
7070   Level: developer
7071 
7072   Notes:
7073   See [Matrix Factorization](sec_matfactor) for additional information.
7074 
7075   Most users should employ the `KSP` interface for linear solvers
7076   instead of working directly with matrix algebra routines such as this.
7077   See, e.g., `KSPCreate()`.
7078 
7079   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7080 
7081   Developer Note:
7082   The Fortran interface is not autogenerated as the
7083   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7084 
7085 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7086           `MatGetOrdering()`, `MatFactorInfo`
7087 @*/
7088 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7089 {
7090   PetscFunctionBegin;
7091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7092   PetscValidType(mat, 2);
7093   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7094   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7095   PetscAssertPointer(info, 5);
7096   PetscAssertPointer(fact, 1);
7097   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7098   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7099   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7100   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7101   MatCheckPreallocated(mat, 2);
7102 
7103   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7104   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7105   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7106   PetscFunctionReturn(PETSC_SUCCESS);
7107 }
7108 
7109 /*@
7110   MatICCFactorSymbolic - Performs symbolic incomplete
7111   Cholesky factorization for a symmetric matrix.  Use
7112   `MatCholeskyFactorNumeric()` to complete the factorization.
7113 
7114   Collective
7115 
7116   Input Parameters:
7117 + fact - the factorized matrix obtained with `MatGetFactor()`
7118 . mat  - the matrix to be factored
7119 . perm - row and column permutation
7120 - info - structure containing
7121 .vb
7122       levels - number of levels of fill.
7123       expected fill - as ratio of original fill.
7124 .ve
7125 
7126   Level: developer
7127 
7128   Notes:
7129   Most users should employ the `KSP` interface for linear solvers
7130   instead of working directly with matrix algebra routines such as this.
7131   See, e.g., `KSPCreate()`.
7132 
7133   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7134 
7135   Developer Note:
7136   The Fortran interface is not autogenerated as the
7137   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7138 
7139 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7140 @*/
7141 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7142 {
7143   PetscFunctionBegin;
7144   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7145   PetscValidType(mat, 2);
7146   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7147   PetscAssertPointer(info, 4);
7148   PetscAssertPointer(fact, 1);
7149   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7150   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7151   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7153   MatCheckPreallocated(mat, 2);
7154 
7155   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7156   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7157   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7158   PetscFunctionReturn(PETSC_SUCCESS);
7159 }
7160 
7161 /*@C
7162   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7163   points to an array of valid matrices, they may be reused to store the new
7164   submatrices.
7165 
7166   Collective
7167 
7168   Input Parameters:
7169 + mat   - the matrix
7170 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7171 . irow  - index set of rows to extract
7172 . icol  - index set of columns to extract
7173 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7174 
7175   Output Parameter:
7176 . submat - the array of submatrices
7177 
7178   Level: advanced
7179 
7180   Notes:
7181   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7182   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7183   to extract a parallel submatrix.
7184 
7185   Some matrix types place restrictions on the row and column
7186   indices, such as that they be sorted or that they be equal to each other.
7187 
7188   The index sets may not have duplicate entries.
7189 
7190   When extracting submatrices from a parallel matrix, each processor can
7191   form a different submatrix by setting the rows and columns of its
7192   individual index sets according to the local submatrix desired.
7193 
7194   When finished using the submatrices, the user should destroy
7195   them with `MatDestroySubMatrices()`.
7196 
7197   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7198   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7199 
7200   This routine creates the matrices in submat; you should NOT create them before
7201   calling it. It also allocates the array of matrix pointers submat.
7202 
7203   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7204   request one row/column in a block, they must request all rows/columns that are in
7205   that block. For example, if the block size is 2 you cannot request just row 0 and
7206   column 0.
7207 
7208   Fortran Note:
7209   One must pass in as `submat` a `Mat` array of size at least `n`+1.
7210 
7211 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7212 @*/
7213 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7214 {
7215   PetscInt  i;
7216   PetscBool eq;
7217 
7218   PetscFunctionBegin;
7219   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7220   PetscValidType(mat, 1);
7221   if (n) {
7222     PetscAssertPointer(irow, 3);
7223     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7224     PetscAssertPointer(icol, 4);
7225     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7226   }
7227   PetscAssertPointer(submat, 6);
7228   if (n && scall == MAT_REUSE_MATRIX) {
7229     PetscAssertPointer(*submat, 6);
7230     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7231   }
7232   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7233   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7234   MatCheckPreallocated(mat, 1);
7235   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7236   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7237   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7238   for (i = 0; i < n; i++) {
7239     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7240     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7241     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7242 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7243     if (mat->boundtocpu && mat->bindingpropagates) {
7244       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7245       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7246     }
7247 #endif
7248   }
7249   PetscFunctionReturn(PETSC_SUCCESS);
7250 }
7251 
7252 /*@C
7253   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7254 
7255   Collective
7256 
7257   Input Parameters:
7258 + mat   - the matrix
7259 . n     - the number of submatrixes to be extracted
7260 . irow  - index set of rows to extract
7261 . icol  - index set of columns to extract
7262 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7263 
7264   Output Parameter:
7265 . submat - the array of submatrices
7266 
7267   Level: advanced
7268 
7269   Note:
7270   This is used by `PCGASM`
7271 
7272 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7273 @*/
7274 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7275 {
7276   PetscInt  i;
7277   PetscBool eq;
7278 
7279   PetscFunctionBegin;
7280   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7281   PetscValidType(mat, 1);
7282   if (n) {
7283     PetscAssertPointer(irow, 3);
7284     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7285     PetscAssertPointer(icol, 4);
7286     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7287   }
7288   PetscAssertPointer(submat, 6);
7289   if (n && scall == MAT_REUSE_MATRIX) {
7290     PetscAssertPointer(*submat, 6);
7291     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7292   }
7293   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7294   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7295   MatCheckPreallocated(mat, 1);
7296 
7297   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7298   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7299   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7300   for (i = 0; i < n; i++) {
7301     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7302     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7303   }
7304   PetscFunctionReturn(PETSC_SUCCESS);
7305 }
7306 
7307 /*@C
7308   MatDestroyMatrices - Destroys an array of matrices.
7309 
7310   Collective
7311 
7312   Input Parameters:
7313 + n   - the number of local matrices
7314 - mat - the matrices (this is a pointer to the array of matrices)
7315 
7316   Level: advanced
7317 
7318   Notes:
7319   Frees not only the matrices, but also the array that contains the matrices
7320 
7321   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7322 
7323   Fortran Note:
7324   Does not free the `mat` array.
7325 
7326 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7327 @*/
7328 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7329 {
7330   PetscInt i;
7331 
7332   PetscFunctionBegin;
7333   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7334   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7335   PetscAssertPointer(mat, 2);
7336 
7337   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7338 
7339   /* memory is allocated even if n = 0 */
7340   PetscCall(PetscFree(*mat));
7341   PetscFunctionReturn(PETSC_SUCCESS);
7342 }
7343 
7344 /*@C
7345   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7346 
7347   Collective
7348 
7349   Input Parameters:
7350 + n   - the number of local matrices
7351 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7352                        sequence of `MatCreateSubMatrices()`)
7353 
7354   Level: advanced
7355 
7356   Note:
7357   Frees not only the matrices, but also the array that contains the matrices
7358 
7359   Fortran Note:
7360   Does not free the `mat` array.
7361 
7362 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7363 @*/
7364 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7365 {
7366   Mat mat0;
7367 
7368   PetscFunctionBegin;
7369   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7370   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7371   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7372   PetscAssertPointer(mat, 2);
7373 
7374   mat0 = (*mat)[0];
7375   if (mat0 && mat0->ops->destroysubmatrices) {
7376     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7377   } else {
7378     PetscCall(MatDestroyMatrices(n, mat));
7379   }
7380   PetscFunctionReturn(PETSC_SUCCESS);
7381 }
7382 
7383 /*@
7384   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7385 
7386   Collective
7387 
7388   Input Parameter:
7389 . mat - the matrix
7390 
7391   Output Parameter:
7392 . matstruct - the sequential matrix with the nonzero structure of `mat`
7393 
7394   Level: developer
7395 
7396 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7397 @*/
7398 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7399 {
7400   PetscFunctionBegin;
7401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7402   PetscAssertPointer(matstruct, 2);
7403 
7404   PetscValidType(mat, 1);
7405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7406   MatCheckPreallocated(mat, 1);
7407 
7408   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7409   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7410   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7411   PetscFunctionReturn(PETSC_SUCCESS);
7412 }
7413 
7414 /*@C
7415   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7416 
7417   Collective
7418 
7419   Input Parameter:
7420 . mat - the matrix
7421 
7422   Level: advanced
7423 
7424   Note:
7425   This is not needed, one can just call `MatDestroy()`
7426 
7427 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7428 @*/
7429 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7430 {
7431   PetscFunctionBegin;
7432   PetscAssertPointer(mat, 1);
7433   PetscCall(MatDestroy(mat));
7434   PetscFunctionReturn(PETSC_SUCCESS);
7435 }
7436 
7437 /*@
7438   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7439   replaces the index sets by larger ones that represent submatrices with
7440   additional overlap.
7441 
7442   Collective
7443 
7444   Input Parameters:
7445 + mat - the matrix
7446 . n   - the number of index sets
7447 . is  - the array of index sets (these index sets will changed during the call)
7448 - ov  - the additional overlap requested
7449 
7450   Options Database Key:
7451 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7452 
7453   Level: developer
7454 
7455   Note:
7456   The computed overlap preserves the matrix block sizes when the blocks are square.
7457   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7458   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7459 
7460 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7461 @*/
7462 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7463 {
7464   PetscInt i, bs, cbs;
7465 
7466   PetscFunctionBegin;
7467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7468   PetscValidType(mat, 1);
7469   PetscValidLogicalCollectiveInt(mat, n, 2);
7470   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7471   if (n) {
7472     PetscAssertPointer(is, 3);
7473     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7474   }
7475   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7476   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7477   MatCheckPreallocated(mat, 1);
7478 
7479   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7480   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7481   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7482   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7483   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7484   if (bs == cbs) {
7485     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7486   }
7487   PetscFunctionReturn(PETSC_SUCCESS);
7488 }
7489 
7490 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7491 
7492 /*@
7493   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7494   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7495   additional overlap.
7496 
7497   Collective
7498 
7499   Input Parameters:
7500 + mat - the matrix
7501 . n   - the number of index sets
7502 . is  - the array of index sets (these index sets will changed during the call)
7503 - ov  - the additional overlap requested
7504 
7505   `   Options Database Key:
7506 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7507 
7508   Level: developer
7509 
7510 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7511 @*/
7512 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7513 {
7514   PetscInt i;
7515 
7516   PetscFunctionBegin;
7517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7518   PetscValidType(mat, 1);
7519   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7520   if (n) {
7521     PetscAssertPointer(is, 3);
7522     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7523   }
7524   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7525   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7526   MatCheckPreallocated(mat, 1);
7527   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7528   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7529   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7530   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7531   PetscFunctionReturn(PETSC_SUCCESS);
7532 }
7533 
7534 /*@
7535   MatGetBlockSize - Returns the matrix block size.
7536 
7537   Not Collective
7538 
7539   Input Parameter:
7540 . mat - the matrix
7541 
7542   Output Parameter:
7543 . bs - block size
7544 
7545   Level: intermediate
7546 
7547   Notes:
7548   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7549 
7550   If the block size has not been set yet this routine returns 1.
7551 
7552 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7553 @*/
7554 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7555 {
7556   PetscFunctionBegin;
7557   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7558   PetscAssertPointer(bs, 2);
7559   *bs = PetscAbs(mat->rmap->bs);
7560   PetscFunctionReturn(PETSC_SUCCESS);
7561 }
7562 
7563 /*@
7564   MatGetBlockSizes - Returns the matrix block row and column sizes.
7565 
7566   Not Collective
7567 
7568   Input Parameter:
7569 . mat - the matrix
7570 
7571   Output Parameters:
7572 + rbs - row block size
7573 - cbs - column block size
7574 
7575   Level: intermediate
7576 
7577   Notes:
7578   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7579   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7580 
7581   If a block size has not been set yet this routine returns 1.
7582 
7583 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7584 @*/
7585 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7586 {
7587   PetscFunctionBegin;
7588   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7589   if (rbs) PetscAssertPointer(rbs, 2);
7590   if (cbs) PetscAssertPointer(cbs, 3);
7591   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7592   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7593   PetscFunctionReturn(PETSC_SUCCESS);
7594 }
7595 
7596 /*@
7597   MatSetBlockSize - Sets the matrix block size.
7598 
7599   Logically Collective
7600 
7601   Input Parameters:
7602 + mat - the matrix
7603 - bs  - block size
7604 
7605   Level: intermediate
7606 
7607   Notes:
7608   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7609   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7610 
7611   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7612   is compatible with the matrix local sizes.
7613 
7614 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7615 @*/
7616 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7617 {
7618   PetscFunctionBegin;
7619   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7620   PetscValidLogicalCollectiveInt(mat, bs, 2);
7621   PetscCall(MatSetBlockSizes(mat, bs, bs));
7622   PetscFunctionReturn(PETSC_SUCCESS);
7623 }
7624 
7625 typedef struct {
7626   PetscInt         n;
7627   IS              *is;
7628   Mat             *mat;
7629   PetscObjectState nonzerostate;
7630   Mat              C;
7631 } EnvelopeData;
7632 
7633 static PetscErrorCode EnvelopeDataDestroy(void *ptr)
7634 {
7635   EnvelopeData *edata = (EnvelopeData *)ptr;
7636 
7637   PetscFunctionBegin;
7638   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7639   PetscCall(PetscFree(edata->is));
7640   PetscCall(PetscFree(edata));
7641   PetscFunctionReturn(PETSC_SUCCESS);
7642 }
7643 
7644 /*@
7645   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7646   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7647 
7648   Collective
7649 
7650   Input Parameter:
7651 . mat - the matrix
7652 
7653   Level: intermediate
7654 
7655   Notes:
7656   There can be zeros within the blocks
7657 
7658   The blocks can overlap between processes, including laying on more than two processes
7659 
7660 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7661 @*/
7662 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7663 {
7664   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7665   PetscInt          *diag, *odiag, sc;
7666   VecScatter         scatter;
7667   PetscScalar       *seqv;
7668   const PetscScalar *parv;
7669   const PetscInt    *ia, *ja;
7670   PetscBool          set, flag, done;
7671   Mat                AA = mat, A;
7672   MPI_Comm           comm;
7673   PetscMPIInt        rank, size, tag;
7674   MPI_Status         status;
7675   PetscContainer     container;
7676   EnvelopeData      *edata;
7677   Vec                seq, par;
7678   IS                 isglobal;
7679 
7680   PetscFunctionBegin;
7681   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7682   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7683   if (!set || !flag) {
7684     /* TODO: only needs nonzero structure of transpose */
7685     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7686     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7687   }
7688   PetscCall(MatAIJGetLocalMat(AA, &A));
7689   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7690   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7691 
7692   PetscCall(MatGetLocalSize(mat, &n, NULL));
7693   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7694   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7695   PetscCallMPI(MPI_Comm_size(comm, &size));
7696   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7697 
7698   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7699 
7700   if (rank > 0) {
7701     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7702     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7703   }
7704   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7705   for (i = 0; i < n; i++) {
7706     env = PetscMax(env, ja[ia[i + 1] - 1]);
7707     II  = rstart + i;
7708     if (env == II) {
7709       starts[lblocks]  = tbs;
7710       sizes[lblocks++] = 1 + II - tbs;
7711       tbs              = 1 + II;
7712     }
7713   }
7714   if (rank < size - 1) {
7715     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7716     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7717   }
7718 
7719   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7720   if (!set || !flag) PetscCall(MatDestroy(&AA));
7721   PetscCall(MatDestroy(&A));
7722 
7723   PetscCall(PetscNew(&edata));
7724   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7725   edata->n = lblocks;
7726   /* create IS needed for extracting blocks from the original matrix */
7727   PetscCall(PetscMalloc1(lblocks, &edata->is));
7728   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7729 
7730   /* Create the resulting inverse matrix structure with preallocation information */
7731   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7732   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7733   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7734   PetscCall(MatSetType(edata->C, MATAIJ));
7735 
7736   /* Communicate the start and end of each row, from each block to the correct rank */
7737   /* TODO: Use PetscSF instead of VecScatter */
7738   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7739   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7740   PetscCall(VecGetArrayWrite(seq, &seqv));
7741   for (PetscInt i = 0; i < lblocks; i++) {
7742     for (PetscInt j = 0; j < sizes[i]; j++) {
7743       seqv[cnt]     = starts[i];
7744       seqv[cnt + 1] = starts[i] + sizes[i];
7745       cnt += 2;
7746     }
7747   }
7748   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7749   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7750   sc -= cnt;
7751   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7752   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7753   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7754   PetscCall(ISDestroy(&isglobal));
7755   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7756   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7757   PetscCall(VecScatterDestroy(&scatter));
7758   PetscCall(VecDestroy(&seq));
7759   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7760   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7761   PetscCall(VecGetArrayRead(par, &parv));
7762   cnt = 0;
7763   PetscCall(MatGetSize(mat, NULL, &n));
7764   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7765     PetscInt start, end, d = 0, od = 0;
7766 
7767     start = (PetscInt)PetscRealPart(parv[cnt]);
7768     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7769     cnt += 2;
7770 
7771     if (start < cstart) {
7772       od += cstart - start + n - cend;
7773       d += cend - cstart;
7774     } else if (start < cend) {
7775       od += n - cend;
7776       d += cend - start;
7777     } else od += n - start;
7778     if (end <= cstart) {
7779       od -= cstart - end + n - cend;
7780       d -= cend - cstart;
7781     } else if (end < cend) {
7782       od -= n - cend;
7783       d -= cend - end;
7784     } else od -= n - end;
7785 
7786     odiag[i] = od;
7787     diag[i]  = d;
7788   }
7789   PetscCall(VecRestoreArrayRead(par, &parv));
7790   PetscCall(VecDestroy(&par));
7791   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7792   PetscCall(PetscFree2(diag, odiag));
7793   PetscCall(PetscFree2(sizes, starts));
7794 
7795   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7796   PetscCall(PetscContainerSetPointer(container, edata));
7797   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7798   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7799   PetscCall(PetscObjectDereference((PetscObject)container));
7800   PetscFunctionReturn(PETSC_SUCCESS);
7801 }
7802 
7803 /*@
7804   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7805 
7806   Collective
7807 
7808   Input Parameters:
7809 + A     - the matrix
7810 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7811 
7812   Output Parameter:
7813 . C - matrix with inverted block diagonal of `A`
7814 
7815   Level: advanced
7816 
7817   Note:
7818   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7819 
7820 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7821 @*/
7822 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7823 {
7824   PetscContainer   container;
7825   EnvelopeData    *edata;
7826   PetscObjectState nonzerostate;
7827 
7828   PetscFunctionBegin;
7829   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7830   if (!container) {
7831     PetscCall(MatComputeVariableBlockEnvelope(A));
7832     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7833   }
7834   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7835   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7836   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7837   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7838 
7839   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7840   *C = edata->C;
7841 
7842   for (PetscInt i = 0; i < edata->n; i++) {
7843     Mat          D;
7844     PetscScalar *dvalues;
7845 
7846     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7847     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7848     PetscCall(MatSeqDenseInvert(D));
7849     PetscCall(MatDenseGetArray(D, &dvalues));
7850     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7851     PetscCall(MatDestroy(&D));
7852   }
7853   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7854   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7855   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7856   PetscFunctionReturn(PETSC_SUCCESS);
7857 }
7858 
7859 /*@
7860   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7861 
7862   Not Collective
7863 
7864   Input Parameters:
7865 + mat     - the matrix
7866 . nblocks - the number of blocks on this process, each block can only exist on a single process
7867 - bsizes  - the block sizes
7868 
7869   Level: intermediate
7870 
7871   Notes:
7872   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7873 
7874   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.
7875 
7876 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7877           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7878 @*/
7879 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7880 {
7881   PetscInt ncnt = 0, nlocal;
7882 
7883   PetscFunctionBegin;
7884   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7885   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7886   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);
7887   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7888   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);
7889   PetscCall(PetscFree(mat->bsizes));
7890   mat->nblocks = nblocks;
7891   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7892   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7893   PetscFunctionReturn(PETSC_SUCCESS);
7894 }
7895 
7896 /*@C
7897   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7898 
7899   Not Collective; No Fortran Support
7900 
7901   Input Parameter:
7902 . mat - the matrix
7903 
7904   Output Parameters:
7905 + nblocks - the number of blocks on this process
7906 - bsizes  - the block sizes
7907 
7908   Level: intermediate
7909 
7910 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7911 @*/
7912 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7913 {
7914   PetscFunctionBegin;
7915   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7916   if (nblocks) *nblocks = mat->nblocks;
7917   if (bsizes) *bsizes = mat->bsizes;
7918   PetscFunctionReturn(PETSC_SUCCESS);
7919 }
7920 
7921 /*@
7922   MatSetBlockSizes - Sets the matrix block row and column sizes.
7923 
7924   Logically Collective
7925 
7926   Input Parameters:
7927 + mat - the matrix
7928 . rbs - row block size
7929 - cbs - column block size
7930 
7931   Level: intermediate
7932 
7933   Notes:
7934   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7935   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7936   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7937 
7938   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7939   are compatible with the matrix local sizes.
7940 
7941   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7942 
7943 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7944 @*/
7945 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7946 {
7947   PetscFunctionBegin;
7948   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7949   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7950   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7951   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7952   if (mat->rmap->refcnt) {
7953     ISLocalToGlobalMapping l2g  = NULL;
7954     PetscLayout            nmap = NULL;
7955 
7956     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7957     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7958     PetscCall(PetscLayoutDestroy(&mat->rmap));
7959     mat->rmap          = nmap;
7960     mat->rmap->mapping = l2g;
7961   }
7962   if (mat->cmap->refcnt) {
7963     ISLocalToGlobalMapping l2g  = NULL;
7964     PetscLayout            nmap = NULL;
7965 
7966     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7967     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7968     PetscCall(PetscLayoutDestroy(&mat->cmap));
7969     mat->cmap          = nmap;
7970     mat->cmap->mapping = l2g;
7971   }
7972   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7973   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7974   PetscFunctionReturn(PETSC_SUCCESS);
7975 }
7976 
7977 /*@
7978   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7979 
7980   Logically Collective
7981 
7982   Input Parameters:
7983 + mat     - the matrix
7984 . fromRow - matrix from which to copy row block size
7985 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7986 
7987   Level: developer
7988 
7989 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7990 @*/
7991 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7992 {
7993   PetscFunctionBegin;
7994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7995   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7996   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7997   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7998   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7999   PetscFunctionReturn(PETSC_SUCCESS);
8000 }
8001 
8002 /*@
8003   MatResidual - Default routine to calculate the residual r = b - Ax
8004 
8005   Collective
8006 
8007   Input Parameters:
8008 + mat - the matrix
8009 . b   - the right-hand-side
8010 - x   - the approximate solution
8011 
8012   Output Parameter:
8013 . r - location to store the residual
8014 
8015   Level: developer
8016 
8017 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8018 @*/
8019 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8020 {
8021   PetscFunctionBegin;
8022   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8023   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8024   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8025   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8026   PetscValidType(mat, 1);
8027   MatCheckPreallocated(mat, 1);
8028   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8029   if (!mat->ops->residual) {
8030     PetscCall(MatMult(mat, x, r));
8031     PetscCall(VecAYPX(r, -1.0, b));
8032   } else {
8033     PetscUseTypeMethod(mat, residual, b, x, r);
8034   }
8035   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8036   PetscFunctionReturn(PETSC_SUCCESS);
8037 }
8038 
8039 /*MC
8040     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
8041 
8042     Synopsis:
8043     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8044 
8045     Not Collective
8046 
8047     Input Parameters:
8048 +   A - the matrix
8049 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8050 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8051 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8052                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8053                  always used.
8054 
8055     Output Parameters:
8056 +   n - number of local rows in the (possibly compressed) matrix
8057 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8058 .   ja - the column indices
8059 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8060            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8061 
8062     Level: developer
8063 
8064     Note:
8065     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
8066 
8067 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
8068 M*/
8069 
8070 /*MC
8071     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
8072 
8073     Synopsis:
8074     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8075 
8076     Not Collective
8077 
8078     Input Parameters:
8079 +   A - the  matrix
8080 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8081 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8082     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8083                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8084                  always used.
8085 .   n - number of local rows in the (possibly compressed) matrix
8086 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8087 .   ja - the column indices
8088 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8089            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8090 
8091     Level: developer
8092 
8093 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
8094 M*/
8095 
8096 /*@C
8097   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8098 
8099   Collective
8100 
8101   Input Parameters:
8102 + mat             - the matrix
8103 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8104 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8105 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8106                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8107                  always used.
8108 
8109   Output Parameters:
8110 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8111 . 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
8112 . ja   - the column indices, use `NULL` if not needed
8113 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8114            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8115 
8116   Level: developer
8117 
8118   Notes:
8119   You CANNOT change any of the ia[] or ja[] values.
8120 
8121   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8122 
8123   Fortran Notes:
8124   Use
8125 .vb
8126     PetscInt, pointer :: ia(:),ja(:)
8127     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8128     ! Access the ith and jth entries via ia(i) and ja(j)
8129 .ve
8130 
8131   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8132 
8133 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8134 @*/
8135 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8136 {
8137   PetscFunctionBegin;
8138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8139   PetscValidType(mat, 1);
8140   if (n) PetscAssertPointer(n, 5);
8141   if (ia) PetscAssertPointer(ia, 6);
8142   if (ja) PetscAssertPointer(ja, 7);
8143   if (done) PetscAssertPointer(done, 8);
8144   MatCheckPreallocated(mat, 1);
8145   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8146   else {
8147     if (done) *done = PETSC_TRUE;
8148     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8149     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8150     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8151   }
8152   PetscFunctionReturn(PETSC_SUCCESS);
8153 }
8154 
8155 /*@C
8156   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8157 
8158   Collective
8159 
8160   Input Parameters:
8161 + mat             - the matrix
8162 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8163 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8164                 symmetrized
8165 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8166                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8167                  always used.
8168 . n               - number of columns in the (possibly compressed) matrix
8169 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8170 - ja              - the row indices
8171 
8172   Output Parameter:
8173 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8174 
8175   Level: developer
8176 
8177 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8178 @*/
8179 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8180 {
8181   PetscFunctionBegin;
8182   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8183   PetscValidType(mat, 1);
8184   PetscAssertPointer(n, 5);
8185   if (ia) PetscAssertPointer(ia, 6);
8186   if (ja) PetscAssertPointer(ja, 7);
8187   PetscAssertPointer(done, 8);
8188   MatCheckPreallocated(mat, 1);
8189   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8190   else {
8191     *done = PETSC_TRUE;
8192     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8193   }
8194   PetscFunctionReturn(PETSC_SUCCESS);
8195 }
8196 
8197 /*@C
8198   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8199 
8200   Collective
8201 
8202   Input Parameters:
8203 + mat             - the matrix
8204 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8205 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8206 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8207                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8208                     always used.
8209 . n               - size of (possibly compressed) matrix
8210 . ia              - the row pointers
8211 - ja              - the column indices
8212 
8213   Output Parameter:
8214 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8215 
8216   Level: developer
8217 
8218   Note:
8219   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8220   us of the array after it has been restored. If you pass `NULL`, it will
8221   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8222 
8223   Fortran Note:
8224   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8225 
8226 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8227 @*/
8228 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8229 {
8230   PetscFunctionBegin;
8231   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8232   PetscValidType(mat, 1);
8233   if (ia) PetscAssertPointer(ia, 6);
8234   if (ja) PetscAssertPointer(ja, 7);
8235   if (done) PetscAssertPointer(done, 8);
8236   MatCheckPreallocated(mat, 1);
8237 
8238   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8239   else {
8240     if (done) *done = PETSC_TRUE;
8241     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8242     if (n) *n = 0;
8243     if (ia) *ia = NULL;
8244     if (ja) *ja = NULL;
8245   }
8246   PetscFunctionReturn(PETSC_SUCCESS);
8247 }
8248 
8249 /*@C
8250   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8251 
8252   Collective
8253 
8254   Input Parameters:
8255 + mat             - the matrix
8256 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8257 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8258 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8259                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8260                     always used.
8261 
8262   Output Parameters:
8263 + n    - size of (possibly compressed) matrix
8264 . ia   - the column pointers
8265 . ja   - the row indices
8266 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8267 
8268   Level: developer
8269 
8270 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8271 @*/
8272 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8273 {
8274   PetscFunctionBegin;
8275   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8276   PetscValidType(mat, 1);
8277   if (ia) PetscAssertPointer(ia, 6);
8278   if (ja) PetscAssertPointer(ja, 7);
8279   PetscAssertPointer(done, 8);
8280   MatCheckPreallocated(mat, 1);
8281 
8282   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8283   else {
8284     *done = PETSC_TRUE;
8285     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8286     if (n) *n = 0;
8287     if (ia) *ia = NULL;
8288     if (ja) *ja = NULL;
8289   }
8290   PetscFunctionReturn(PETSC_SUCCESS);
8291 }
8292 
8293 /*@
8294   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8295   `MatGetColumnIJ()`.
8296 
8297   Collective
8298 
8299   Input Parameters:
8300 + mat        - the matrix
8301 . ncolors    - maximum color value
8302 . n          - number of entries in colorarray
8303 - colorarray - array indicating color for each column
8304 
8305   Output Parameter:
8306 . iscoloring - coloring generated using colorarray information
8307 
8308   Level: developer
8309 
8310 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8311 @*/
8312 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8313 {
8314   PetscFunctionBegin;
8315   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8316   PetscValidType(mat, 1);
8317   PetscAssertPointer(colorarray, 4);
8318   PetscAssertPointer(iscoloring, 5);
8319   MatCheckPreallocated(mat, 1);
8320 
8321   if (!mat->ops->coloringpatch) {
8322     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8323   } else {
8324     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8325   }
8326   PetscFunctionReturn(PETSC_SUCCESS);
8327 }
8328 
8329 /*@
8330   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8331 
8332   Logically Collective
8333 
8334   Input Parameter:
8335 . mat - the factored matrix to be reset
8336 
8337   Level: developer
8338 
8339   Notes:
8340   This routine should be used only with factored matrices formed by in-place
8341   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8342   format).  This option can save memory, for example, when solving nonlinear
8343   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8344   ILU(0) preconditioner.
8345 
8346   One can specify in-place ILU(0) factorization by calling
8347 .vb
8348      PCType(pc,PCILU);
8349      PCFactorSeUseInPlace(pc);
8350 .ve
8351   or by using the options -pc_type ilu -pc_factor_in_place
8352 
8353   In-place factorization ILU(0) can also be used as a local
8354   solver for the blocks within the block Jacobi or additive Schwarz
8355   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8356   for details on setting local solver options.
8357 
8358   Most users should employ the `KSP` interface for linear solvers
8359   instead of working directly with matrix algebra routines such as this.
8360   See, e.g., `KSPCreate()`.
8361 
8362 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8363 @*/
8364 PetscErrorCode MatSetUnfactored(Mat mat)
8365 {
8366   PetscFunctionBegin;
8367   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8368   PetscValidType(mat, 1);
8369   MatCheckPreallocated(mat, 1);
8370   mat->factortype = MAT_FACTOR_NONE;
8371   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8372   PetscUseTypeMethod(mat, setunfactored);
8373   PetscFunctionReturn(PETSC_SUCCESS);
8374 }
8375 
8376 /*MC
8377     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8378 
8379     Synopsis:
8380     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8381 
8382     Not Collective
8383 
8384     Input Parameter:
8385 .   x - matrix
8386 
8387     Output Parameters:
8388 +   xx_v - the Fortran pointer to the array
8389 -   ierr - error code
8390 
8391     Example of Usage:
8392 .vb
8393       PetscScalar, pointer xx_v(:,:)
8394       ....
8395       call MatDenseGetArrayF90(x,xx_v,ierr)
8396       a = xx_v(3)
8397       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8398 .ve
8399 
8400     Level: advanced
8401 
8402 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8403 M*/
8404 
8405 /*MC
8406     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8407     accessed with `MatDenseGetArrayF90()`.
8408 
8409     Synopsis:
8410     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8411 
8412     Not Collective
8413 
8414     Input Parameters:
8415 +   x - matrix
8416 -   xx_v - the Fortran90 pointer to the array
8417 
8418     Output Parameter:
8419 .   ierr - error code
8420 
8421     Example of Usage:
8422 .vb
8423        PetscScalar, pointer xx_v(:,:)
8424        ....
8425        call MatDenseGetArrayF90(x,xx_v,ierr)
8426        a = xx_v(3)
8427        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8428 .ve
8429 
8430     Level: advanced
8431 
8432 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8433 M*/
8434 
8435 /*MC
8436     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8437 
8438     Synopsis:
8439     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8440 
8441     Not Collective
8442 
8443     Input Parameter:
8444 .   x - matrix
8445 
8446     Output Parameters:
8447 +   xx_v - the Fortran pointer to the array
8448 -   ierr - error code
8449 
8450     Example of Usage:
8451 .vb
8452       PetscScalar, pointer xx_v(:)
8453       ....
8454       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8455       a = xx_v(3)
8456       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8457 .ve
8458 
8459     Level: advanced
8460 
8461 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8462 M*/
8463 
8464 /*MC
8465     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8466     accessed with `MatSeqAIJGetArrayF90()`.
8467 
8468     Synopsis:
8469     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8470 
8471     Not Collective
8472 
8473     Input Parameters:
8474 +   x - matrix
8475 -   xx_v - the Fortran90 pointer to the array
8476 
8477     Output Parameter:
8478 .   ierr - error code
8479 
8480     Example of Usage:
8481 .vb
8482        PetscScalar, pointer xx_v(:)
8483        ....
8484        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8485        a = xx_v(3)
8486        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8487 .ve
8488 
8489     Level: advanced
8490 
8491 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8492 M*/
8493 
8494 /*@
8495   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8496   as the original matrix.
8497 
8498   Collective
8499 
8500   Input Parameters:
8501 + mat   - the original matrix
8502 . isrow - parallel `IS` containing the rows this processor should obtain
8503 . 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.
8504 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8505 
8506   Output Parameter:
8507 . newmat - the new submatrix, of the same type as the original matrix
8508 
8509   Level: advanced
8510 
8511   Notes:
8512   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8513 
8514   Some matrix types place restrictions on the row and column indices, such
8515   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;
8516   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8517 
8518   The index sets may not have duplicate entries.
8519 
8520   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8521   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8522   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8523   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8524   you are finished using it.
8525 
8526   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8527   the input matrix.
8528 
8529   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8530 
8531   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8532   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8533 
8534   Example usage:
8535   Consider the following 8x8 matrix with 34 non-zero values, that is
8536   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8537   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8538   as follows
8539 .vb
8540             1  2  0  |  0  3  0  |  0  4
8541     Proc0   0  5  6  |  7  0  0  |  8  0
8542             9  0 10  | 11  0  0  | 12  0
8543     -------------------------------------
8544            13  0 14  | 15 16 17  |  0  0
8545     Proc1   0 18  0  | 19 20 21  |  0  0
8546             0  0  0  | 22 23  0  | 24  0
8547     -------------------------------------
8548     Proc2  25 26 27  |  0  0 28  | 29  0
8549            30  0  0  | 31 32 33  |  0 34
8550 .ve
8551 
8552   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8553 
8554 .vb
8555             2  0  |  0  3  0  |  0
8556     Proc0   5  6  |  7  0  0  |  8
8557     -------------------------------
8558     Proc1  18  0  | 19 20 21  |  0
8559     -------------------------------
8560     Proc2  26 27  |  0  0 28  | 29
8561             0  0  | 31 32 33  |  0
8562 .ve
8563 
8564 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8565 @*/
8566 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8567 {
8568   PetscMPIInt size;
8569   Mat        *local;
8570   IS          iscoltmp;
8571   PetscBool   flg;
8572 
8573   PetscFunctionBegin;
8574   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8575   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8576   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8577   PetscAssertPointer(newmat, 5);
8578   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8579   PetscValidType(mat, 1);
8580   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8581   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8582 
8583   MatCheckPreallocated(mat, 1);
8584   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8585 
8586   if (!iscol || isrow == iscol) {
8587     PetscBool   stride;
8588     PetscMPIInt grabentirematrix = 0, grab;
8589     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8590     if (stride) {
8591       PetscInt first, step, n, rstart, rend;
8592       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8593       if (step == 1) {
8594         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8595         if (rstart == first) {
8596           PetscCall(ISGetLocalSize(isrow, &n));
8597           if (n == rend - rstart) grabentirematrix = 1;
8598         }
8599       }
8600     }
8601     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8602     if (grab) {
8603       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8604       if (cll == MAT_INITIAL_MATRIX) {
8605         *newmat = mat;
8606         PetscCall(PetscObjectReference((PetscObject)mat));
8607       }
8608       PetscFunctionReturn(PETSC_SUCCESS);
8609     }
8610   }
8611 
8612   if (!iscol) {
8613     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8614   } else {
8615     iscoltmp = iscol;
8616   }
8617 
8618   /* if original matrix is on just one processor then use submatrix generated */
8619   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8620     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8621     goto setproperties;
8622   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8623     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8624     *newmat = *local;
8625     PetscCall(PetscFree(local));
8626     goto setproperties;
8627   } else if (!mat->ops->createsubmatrix) {
8628     /* Create a new matrix type that implements the operation using the full matrix */
8629     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8630     switch (cll) {
8631     case MAT_INITIAL_MATRIX:
8632       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8633       break;
8634     case MAT_REUSE_MATRIX:
8635       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8636       break;
8637     default:
8638       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8639     }
8640     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8641     goto setproperties;
8642   }
8643 
8644   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8645   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8646   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8647 
8648 setproperties:
8649   if ((*newmat)->symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->structurally_symmetric == PETSC_BOOL3_UNKNOWN && (*newmat)->spd == PETSC_BOOL3_UNKNOWN && (*newmat)->hermitian == PETSC_BOOL3_UNKNOWN) {
8650     PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8651     if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8652   }
8653   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8654   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8655   PetscFunctionReturn(PETSC_SUCCESS);
8656 }
8657 
8658 /*@
8659   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8660 
8661   Not Collective
8662 
8663   Input Parameters:
8664 + A - the matrix we wish to propagate options from
8665 - B - the matrix we wish to propagate options to
8666 
8667   Level: beginner
8668 
8669   Note:
8670   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8671 
8672 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8673 @*/
8674 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8675 {
8676   PetscFunctionBegin;
8677   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8678   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8679   B->symmetry_eternal            = A->symmetry_eternal;
8680   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8681   B->symmetric                   = A->symmetric;
8682   B->structurally_symmetric      = A->structurally_symmetric;
8683   B->spd                         = A->spd;
8684   B->hermitian                   = A->hermitian;
8685   PetscFunctionReturn(PETSC_SUCCESS);
8686 }
8687 
8688 /*@
8689   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8690   used during the assembly process to store values that belong to
8691   other processors.
8692 
8693   Not Collective
8694 
8695   Input Parameters:
8696 + mat   - the matrix
8697 . size  - the initial size of the stash.
8698 - bsize - the initial size of the block-stash(if used).
8699 
8700   Options Database Keys:
8701 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8702 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8703 
8704   Level: intermediate
8705 
8706   Notes:
8707   The block-stash is used for values set with `MatSetValuesBlocked()` while
8708   the stash is used for values set with `MatSetValues()`
8709 
8710   Run with the option -info and look for output of the form
8711   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8712   to determine the appropriate value, MM, to use for size and
8713   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8714   to determine the value, BMM to use for bsize
8715 
8716 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8717 @*/
8718 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8719 {
8720   PetscFunctionBegin;
8721   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8722   PetscValidType(mat, 1);
8723   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8724   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8725   PetscFunctionReturn(PETSC_SUCCESS);
8726 }
8727 
8728 /*@
8729   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8730   the matrix
8731 
8732   Neighbor-wise Collective
8733 
8734   Input Parameters:
8735 + A - the matrix
8736 . x - the vector to be multiplied by the interpolation operator
8737 - y - the vector to be added to the result
8738 
8739   Output Parameter:
8740 . w - the resulting vector
8741 
8742   Level: intermediate
8743 
8744   Notes:
8745   `w` may be the same vector as `y`.
8746 
8747   This allows one to use either the restriction or interpolation (its transpose)
8748   matrix to do the interpolation
8749 
8750 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8751 @*/
8752 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8753 {
8754   PetscInt M, N, Ny;
8755 
8756   PetscFunctionBegin;
8757   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8758   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8759   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8760   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8761   PetscCall(MatGetSize(A, &M, &N));
8762   PetscCall(VecGetSize(y, &Ny));
8763   if (M == Ny) {
8764     PetscCall(MatMultAdd(A, x, y, w));
8765   } else {
8766     PetscCall(MatMultTransposeAdd(A, x, y, w));
8767   }
8768   PetscFunctionReturn(PETSC_SUCCESS);
8769 }
8770 
8771 /*@
8772   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8773   the matrix
8774 
8775   Neighbor-wise Collective
8776 
8777   Input Parameters:
8778 + A - the matrix
8779 - x - the vector to be interpolated
8780 
8781   Output Parameter:
8782 . y - the resulting vector
8783 
8784   Level: intermediate
8785 
8786   Note:
8787   This allows one to use either the restriction or interpolation (its transpose)
8788   matrix to do the interpolation
8789 
8790 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8791 @*/
8792 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8793 {
8794   PetscInt M, N, Ny;
8795 
8796   PetscFunctionBegin;
8797   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8798   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8799   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8800   PetscCall(MatGetSize(A, &M, &N));
8801   PetscCall(VecGetSize(y, &Ny));
8802   if (M == Ny) {
8803     PetscCall(MatMult(A, x, y));
8804   } else {
8805     PetscCall(MatMultTranspose(A, x, y));
8806   }
8807   PetscFunctionReturn(PETSC_SUCCESS);
8808 }
8809 
8810 /*@
8811   MatRestrict - $y = A*x$ or $A^T*x$
8812 
8813   Neighbor-wise Collective
8814 
8815   Input Parameters:
8816 + A - the matrix
8817 - x - the vector to be restricted
8818 
8819   Output Parameter:
8820 . y - the resulting vector
8821 
8822   Level: intermediate
8823 
8824   Note:
8825   This allows one to use either the restriction or interpolation (its transpose)
8826   matrix to do the restriction
8827 
8828 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8829 @*/
8830 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8831 {
8832   PetscInt M, N, Nx;
8833 
8834   PetscFunctionBegin;
8835   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8836   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8837   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8838   PetscCall(MatGetSize(A, &M, &N));
8839   PetscCall(VecGetSize(x, &Nx));
8840   if (M == Nx) {
8841     PetscCall(MatMultTranspose(A, x, y));
8842   } else {
8843     PetscCall(MatMult(A, x, y));
8844   }
8845   PetscFunctionReturn(PETSC_SUCCESS);
8846 }
8847 
8848 /*@
8849   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8850 
8851   Neighbor-wise Collective
8852 
8853   Input Parameters:
8854 + A - the matrix
8855 . x - the input dense matrix to be multiplied
8856 - w - the input dense matrix to be added to the result
8857 
8858   Output Parameter:
8859 . y - the output dense matrix
8860 
8861   Level: intermediate
8862 
8863   Note:
8864   This allows one to use either the restriction or interpolation (its transpose)
8865   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8866   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8867 
8868 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8869 @*/
8870 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8871 {
8872   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8873   PetscBool trans = PETSC_TRUE;
8874   MatReuse  reuse = MAT_INITIAL_MATRIX;
8875 
8876   PetscFunctionBegin;
8877   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8878   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8879   PetscValidType(x, 2);
8880   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8881   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8882   PetscCall(MatGetSize(A, &M, &N));
8883   PetscCall(MatGetSize(x, &Mx, &Nx));
8884   if (N == Mx) trans = PETSC_FALSE;
8885   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);
8886   Mo = trans ? N : M;
8887   if (*y) {
8888     PetscCall(MatGetSize(*y, &My, &Ny));
8889     if (Mo == My && Nx == Ny) {
8890       reuse = MAT_REUSE_MATRIX;
8891     } else {
8892       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);
8893       PetscCall(MatDestroy(y));
8894     }
8895   }
8896 
8897   if (w && *y == w) { /* this is to minimize changes in PCMG */
8898     PetscBool flg;
8899 
8900     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8901     if (w) {
8902       PetscInt My, Ny, Mw, Nw;
8903 
8904       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8905       PetscCall(MatGetSize(*y, &My, &Ny));
8906       PetscCall(MatGetSize(w, &Mw, &Nw));
8907       if (!flg || My != Mw || Ny != Nw) w = NULL;
8908     }
8909     if (!w) {
8910       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8911       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8912       PetscCall(PetscObjectDereference((PetscObject)w));
8913     } else {
8914       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8915     }
8916   }
8917   if (!trans) {
8918     PetscCall(MatMatMult(A, x, reuse, PETSC_DETERMINE, y));
8919   } else {
8920     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DETERMINE, y));
8921   }
8922   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8923   PetscFunctionReturn(PETSC_SUCCESS);
8924 }
8925 
8926 /*@
8927   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8928 
8929   Neighbor-wise Collective
8930 
8931   Input Parameters:
8932 + A - the matrix
8933 - x - the input dense matrix
8934 
8935   Output Parameter:
8936 . y - the output dense matrix
8937 
8938   Level: intermediate
8939 
8940   Note:
8941   This allows one to use either the restriction or interpolation (its transpose)
8942   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8943   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8944 
8945 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8946 @*/
8947 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8948 {
8949   PetscFunctionBegin;
8950   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8951   PetscFunctionReturn(PETSC_SUCCESS);
8952 }
8953 
8954 /*@
8955   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8956 
8957   Neighbor-wise Collective
8958 
8959   Input Parameters:
8960 + A - the matrix
8961 - x - the input dense matrix
8962 
8963   Output Parameter:
8964 . y - the output dense matrix
8965 
8966   Level: intermediate
8967 
8968   Note:
8969   This allows one to use either the restriction or interpolation (its transpose)
8970   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8971   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8972 
8973 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8974 @*/
8975 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8976 {
8977   PetscFunctionBegin;
8978   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8979   PetscFunctionReturn(PETSC_SUCCESS);
8980 }
8981 
8982 /*@
8983   MatGetNullSpace - retrieves the null space of a matrix.
8984 
8985   Logically Collective
8986 
8987   Input Parameters:
8988 + mat    - the matrix
8989 - nullsp - the null space object
8990 
8991   Level: developer
8992 
8993 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8994 @*/
8995 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8996 {
8997   PetscFunctionBegin;
8998   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8999   PetscAssertPointer(nullsp, 2);
9000   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
9001   PetscFunctionReturn(PETSC_SUCCESS);
9002 }
9003 
9004 /*@C
9005   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
9006 
9007   Logically Collective
9008 
9009   Input Parameters:
9010 + n   - the number of matrices
9011 - mat - the array of matrices
9012 
9013   Output Parameters:
9014 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
9015 
9016   Level: developer
9017 
9018   Note:
9019   Call `MatRestoreNullspaces()` to provide these to another array of matrices
9020 
9021 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9022           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
9023 @*/
9024 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9025 {
9026   PetscFunctionBegin;
9027   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9028   PetscAssertPointer(mat, 2);
9029   PetscAssertPointer(nullsp, 3);
9030 
9031   PetscCall(PetscCalloc1(3 * n, nullsp));
9032   for (PetscInt i = 0; i < n; i++) {
9033     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9034     (*nullsp)[i] = mat[i]->nullsp;
9035     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
9036     (*nullsp)[n + i] = mat[i]->nearnullsp;
9037     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
9038     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
9039     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
9040   }
9041   PetscFunctionReturn(PETSC_SUCCESS);
9042 }
9043 
9044 /*@C
9045   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
9046 
9047   Logically Collective
9048 
9049   Input Parameters:
9050 + n      - the number of matrices
9051 . mat    - the array of matrices
9052 - nullsp - an array of null spaces
9053 
9054   Level: developer
9055 
9056   Note:
9057   Call `MatGetNullSpaces()` to create `nullsp`
9058 
9059 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9060           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9061 @*/
9062 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9063 {
9064   PetscFunctionBegin;
9065   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9066   PetscAssertPointer(mat, 2);
9067   PetscAssertPointer(nullsp, 3);
9068   PetscAssertPointer(*nullsp, 3);
9069 
9070   for (PetscInt i = 0; i < n; i++) {
9071     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9072     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9073     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9074     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9075     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9076     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9077     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9078   }
9079   PetscCall(PetscFree(*nullsp));
9080   PetscFunctionReturn(PETSC_SUCCESS);
9081 }
9082 
9083 /*@
9084   MatSetNullSpace - attaches a null space to a matrix.
9085 
9086   Logically Collective
9087 
9088   Input Parameters:
9089 + mat    - the matrix
9090 - nullsp - the null space object
9091 
9092   Level: advanced
9093 
9094   Notes:
9095   This null space is used by the `KSP` linear solvers to solve singular systems.
9096 
9097   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`
9098 
9099   For inconsistent singular systems (linear systems where the right-hand side is not in the range of the operator) the `KSP` residuals will not converge to
9100   to zero but the linear system will still be solved in a least squares sense.
9101 
9102   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9103   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)$.
9104   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
9105   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
9106   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$).
9107   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9108 
9109   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9110   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9111   routine also automatically calls `MatSetTransposeNullSpace()`.
9112 
9113   The user should call `MatNullSpaceDestroy()`.
9114 
9115 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9116           `KSPSetPCSide()`
9117 @*/
9118 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9119 {
9120   PetscFunctionBegin;
9121   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9122   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9123   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9124   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9125   mat->nullsp = nullsp;
9126   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9127   PetscFunctionReturn(PETSC_SUCCESS);
9128 }
9129 
9130 /*@
9131   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9132 
9133   Logically Collective
9134 
9135   Input Parameters:
9136 + mat    - the matrix
9137 - nullsp - the null space object
9138 
9139   Level: developer
9140 
9141 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9142 @*/
9143 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9144 {
9145   PetscFunctionBegin;
9146   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9147   PetscValidType(mat, 1);
9148   PetscAssertPointer(nullsp, 2);
9149   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9150   PetscFunctionReturn(PETSC_SUCCESS);
9151 }
9152 
9153 /*@
9154   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9155 
9156   Logically Collective
9157 
9158   Input Parameters:
9159 + mat    - the matrix
9160 - nullsp - the null space object
9161 
9162   Level: advanced
9163 
9164   Notes:
9165   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9166 
9167   See `MatSetNullSpace()`
9168 
9169 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9170 @*/
9171 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9172 {
9173   PetscFunctionBegin;
9174   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9175   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9176   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9177   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9178   mat->transnullsp = nullsp;
9179   PetscFunctionReturn(PETSC_SUCCESS);
9180 }
9181 
9182 /*@
9183   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9184   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9185 
9186   Logically Collective
9187 
9188   Input Parameters:
9189 + mat    - the matrix
9190 - nullsp - the null space object
9191 
9192   Level: advanced
9193 
9194   Notes:
9195   Overwrites any previous near null space that may have been attached
9196 
9197   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9198 
9199 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9200 @*/
9201 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9202 {
9203   PetscFunctionBegin;
9204   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9205   PetscValidType(mat, 1);
9206   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9207   MatCheckPreallocated(mat, 1);
9208   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9209   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9210   mat->nearnullsp = nullsp;
9211   PetscFunctionReturn(PETSC_SUCCESS);
9212 }
9213 
9214 /*@
9215   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9216 
9217   Not Collective
9218 
9219   Input Parameter:
9220 . mat - the matrix
9221 
9222   Output Parameter:
9223 . nullsp - the null space object, `NULL` if not set
9224 
9225   Level: advanced
9226 
9227 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9228 @*/
9229 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9230 {
9231   PetscFunctionBegin;
9232   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9233   PetscValidType(mat, 1);
9234   PetscAssertPointer(nullsp, 2);
9235   MatCheckPreallocated(mat, 1);
9236   *nullsp = mat->nearnullsp;
9237   PetscFunctionReturn(PETSC_SUCCESS);
9238 }
9239 
9240 /*@
9241   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9242 
9243   Collective
9244 
9245   Input Parameters:
9246 + mat  - the matrix
9247 . row  - row/column permutation
9248 - info - information on desired factorization process
9249 
9250   Level: developer
9251 
9252   Notes:
9253   Probably really in-place only when level of fill is zero, otherwise allocates
9254   new space to store factored matrix and deletes previous memory.
9255 
9256   Most users should employ the `KSP` interface for linear solvers
9257   instead of working directly with matrix algebra routines such as this.
9258   See, e.g., `KSPCreate()`.
9259 
9260   Developer Note:
9261   The Fortran interface is not autogenerated as the
9262   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9263 
9264 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9265 @*/
9266 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9267 {
9268   PetscFunctionBegin;
9269   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9270   PetscValidType(mat, 1);
9271   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9272   PetscAssertPointer(info, 3);
9273   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9274   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9275   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9276   MatCheckPreallocated(mat, 1);
9277   PetscUseTypeMethod(mat, iccfactor, row, info);
9278   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9279   PetscFunctionReturn(PETSC_SUCCESS);
9280 }
9281 
9282 /*@
9283   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9284   ghosted ones.
9285 
9286   Not Collective
9287 
9288   Input Parameters:
9289 + mat  - the matrix
9290 - diag - the diagonal values, including ghost ones
9291 
9292   Level: developer
9293 
9294   Notes:
9295   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9296 
9297   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9298 
9299 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9300 @*/
9301 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9302 {
9303   PetscMPIInt size;
9304 
9305   PetscFunctionBegin;
9306   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9307   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9308   PetscValidType(mat, 1);
9309 
9310   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9311   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9312   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9313   if (size == 1) {
9314     PetscInt n, m;
9315     PetscCall(VecGetSize(diag, &n));
9316     PetscCall(MatGetSize(mat, NULL, &m));
9317     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9318     PetscCall(MatDiagonalScale(mat, NULL, diag));
9319   } else {
9320     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9321   }
9322   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9323   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9324   PetscFunctionReturn(PETSC_SUCCESS);
9325 }
9326 
9327 /*@
9328   MatGetInertia - Gets the inertia from a factored matrix
9329 
9330   Collective
9331 
9332   Input Parameter:
9333 . mat - the matrix
9334 
9335   Output Parameters:
9336 + nneg  - number of negative eigenvalues
9337 . nzero - number of zero eigenvalues
9338 - npos  - number of positive eigenvalues
9339 
9340   Level: advanced
9341 
9342   Note:
9343   Matrix must have been factored by `MatCholeskyFactor()`
9344 
9345 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9346 @*/
9347 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9348 {
9349   PetscFunctionBegin;
9350   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9351   PetscValidType(mat, 1);
9352   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9353   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9354   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9355   PetscFunctionReturn(PETSC_SUCCESS);
9356 }
9357 
9358 /*@C
9359   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9360 
9361   Neighbor-wise Collective
9362 
9363   Input Parameters:
9364 + mat - the factored matrix obtained with `MatGetFactor()`
9365 - b   - the right-hand-side vectors
9366 
9367   Output Parameter:
9368 . x - the result vectors
9369 
9370   Level: developer
9371 
9372   Note:
9373   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9374   call `MatSolves`(A,x,x).
9375 
9376 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9377 @*/
9378 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9379 {
9380   PetscFunctionBegin;
9381   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9382   PetscValidType(mat, 1);
9383   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9384   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9385   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9386 
9387   MatCheckPreallocated(mat, 1);
9388   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9389   PetscUseTypeMethod(mat, solves, b, x);
9390   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9391   PetscFunctionReturn(PETSC_SUCCESS);
9392 }
9393 
9394 /*@
9395   MatIsSymmetric - Test whether a matrix is symmetric
9396 
9397   Collective
9398 
9399   Input Parameters:
9400 + A   - the matrix to test
9401 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9402 
9403   Output Parameter:
9404 . flg - the result
9405 
9406   Level: intermediate
9407 
9408   Notes:
9409   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9410 
9411   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9412 
9413   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9414   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9415 
9416 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9417           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9418 @*/
9419 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9420 {
9421   PetscFunctionBegin;
9422   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9423   PetscAssertPointer(flg, 3);
9424   if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric);
9425   else {
9426     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9427     else PetscCall(MatIsTranspose(A, A, tol, flg));
9428     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9429   }
9430   PetscFunctionReturn(PETSC_SUCCESS);
9431 }
9432 
9433 /*@
9434   MatIsHermitian - Test whether a matrix is Hermitian
9435 
9436   Collective
9437 
9438   Input Parameters:
9439 + A   - the matrix to test
9440 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9441 
9442   Output Parameter:
9443 . flg - the result
9444 
9445   Level: intermediate
9446 
9447   Notes:
9448   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9449 
9450   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9451 
9452   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9453   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9454 
9455 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9456           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9457 @*/
9458 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9459 {
9460   PetscFunctionBegin;
9461   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9462   PetscAssertPointer(flg, 3);
9463   if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian);
9464   else {
9465     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9466     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9467     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9468   }
9469   PetscFunctionReturn(PETSC_SUCCESS);
9470 }
9471 
9472 /*@
9473   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9474 
9475   Not Collective
9476 
9477   Input Parameter:
9478 . A - the matrix to check
9479 
9480   Output Parameters:
9481 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9482 - flg - the result (only valid if set is `PETSC_TRUE`)
9483 
9484   Level: advanced
9485 
9486   Notes:
9487   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9488   if you want it explicitly checked
9489 
9490   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9491   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9492 
9493 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9494 @*/
9495 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9496 {
9497   PetscFunctionBegin;
9498   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9499   PetscAssertPointer(set, 2);
9500   PetscAssertPointer(flg, 3);
9501   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9502     *set = PETSC_TRUE;
9503     *flg = PetscBool3ToBool(A->symmetric);
9504   } else {
9505     *set = PETSC_FALSE;
9506   }
9507   PetscFunctionReturn(PETSC_SUCCESS);
9508 }
9509 
9510 /*@
9511   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9512 
9513   Not Collective
9514 
9515   Input Parameter:
9516 . A - the matrix to check
9517 
9518   Output Parameters:
9519 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9520 - flg - the result (only valid if set is `PETSC_TRUE`)
9521 
9522   Level: advanced
9523 
9524   Notes:
9525   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9526 
9527   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9528   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9529 
9530 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9531 @*/
9532 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9533 {
9534   PetscFunctionBegin;
9535   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9536   PetscAssertPointer(set, 2);
9537   PetscAssertPointer(flg, 3);
9538   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9539     *set = PETSC_TRUE;
9540     *flg = PetscBool3ToBool(A->spd);
9541   } else {
9542     *set = PETSC_FALSE;
9543   }
9544   PetscFunctionReturn(PETSC_SUCCESS);
9545 }
9546 
9547 /*@
9548   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9549 
9550   Not Collective
9551 
9552   Input Parameter:
9553 . A - the matrix to check
9554 
9555   Output Parameters:
9556 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9557 - flg - the result (only valid if set is `PETSC_TRUE`)
9558 
9559   Level: advanced
9560 
9561   Notes:
9562   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9563   if you want it explicitly checked
9564 
9565   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9566   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9567 
9568 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9569 @*/
9570 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9571 {
9572   PetscFunctionBegin;
9573   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9574   PetscAssertPointer(set, 2);
9575   PetscAssertPointer(flg, 3);
9576   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9577     *set = PETSC_TRUE;
9578     *flg = PetscBool3ToBool(A->hermitian);
9579   } else {
9580     *set = PETSC_FALSE;
9581   }
9582   PetscFunctionReturn(PETSC_SUCCESS);
9583 }
9584 
9585 /*@
9586   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9587 
9588   Collective
9589 
9590   Input Parameter:
9591 . A - the matrix to test
9592 
9593   Output Parameter:
9594 . flg - the result
9595 
9596   Level: intermediate
9597 
9598   Notes:
9599   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9600 
9601   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
9602   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9603 
9604 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9605 @*/
9606 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9607 {
9608   PetscFunctionBegin;
9609   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9610   PetscAssertPointer(flg, 2);
9611   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9612     *flg = PetscBool3ToBool(A->structurally_symmetric);
9613   } else {
9614     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9615     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9616   }
9617   PetscFunctionReturn(PETSC_SUCCESS);
9618 }
9619 
9620 /*@
9621   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9622 
9623   Not Collective
9624 
9625   Input Parameter:
9626 . A - the matrix to check
9627 
9628   Output Parameters:
9629 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9630 - flg - the result (only valid if set is PETSC_TRUE)
9631 
9632   Level: advanced
9633 
9634   Notes:
9635   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
9636   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9637 
9638   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9639 
9640 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9641 @*/
9642 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9643 {
9644   PetscFunctionBegin;
9645   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9646   PetscAssertPointer(set, 2);
9647   PetscAssertPointer(flg, 3);
9648   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9649     *set = PETSC_TRUE;
9650     *flg = PetscBool3ToBool(A->structurally_symmetric);
9651   } else {
9652     *set = PETSC_FALSE;
9653   }
9654   PetscFunctionReturn(PETSC_SUCCESS);
9655 }
9656 
9657 /*@
9658   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9659   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9660 
9661   Not Collective
9662 
9663   Input Parameter:
9664 . mat - the matrix
9665 
9666   Output Parameters:
9667 + nstash    - the size of the stash
9668 . reallocs  - the number of additional mallocs incurred.
9669 . bnstash   - the size of the block stash
9670 - breallocs - the number of additional mallocs incurred.in the block stash
9671 
9672   Level: advanced
9673 
9674 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9675 @*/
9676 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9677 {
9678   PetscFunctionBegin;
9679   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9680   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9681   PetscFunctionReturn(PETSC_SUCCESS);
9682 }
9683 
9684 /*@
9685   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9686   parallel layout, `PetscLayout` for rows and columns
9687 
9688   Collective
9689 
9690   Input Parameter:
9691 . mat - the matrix
9692 
9693   Output Parameters:
9694 + right - (optional) vector that the matrix can be multiplied against
9695 - left  - (optional) vector that the matrix vector product can be stored in
9696 
9697   Level: advanced
9698 
9699   Notes:
9700   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()`.
9701 
9702   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9703 
9704 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9705 @*/
9706 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9707 {
9708   PetscFunctionBegin;
9709   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9710   PetscValidType(mat, 1);
9711   if (mat->ops->getvecs) {
9712     PetscUseTypeMethod(mat, getvecs, right, left);
9713   } else {
9714     if (right) {
9715       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9716       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9717       PetscCall(VecSetType(*right, mat->defaultvectype));
9718 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9719       if (mat->boundtocpu && mat->bindingpropagates) {
9720         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9721         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9722       }
9723 #endif
9724     }
9725     if (left) {
9726       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9727       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9728       PetscCall(VecSetType(*left, mat->defaultvectype));
9729 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9730       if (mat->boundtocpu && mat->bindingpropagates) {
9731         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9732         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9733       }
9734 #endif
9735     }
9736   }
9737   PetscFunctionReturn(PETSC_SUCCESS);
9738 }
9739 
9740 /*@
9741   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9742   with default values.
9743 
9744   Not Collective
9745 
9746   Input Parameter:
9747 . info - the `MatFactorInfo` data structure
9748 
9749   Level: developer
9750 
9751   Notes:
9752   The solvers are generally used through the `KSP` and `PC` objects, for example
9753   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9754 
9755   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9756 
9757 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9758 @*/
9759 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9760 {
9761   PetscFunctionBegin;
9762   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9763   PetscFunctionReturn(PETSC_SUCCESS);
9764 }
9765 
9766 /*@
9767   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9768 
9769   Collective
9770 
9771   Input Parameters:
9772 + mat - the factored matrix
9773 - is  - the index set defining the Schur indices (0-based)
9774 
9775   Level: advanced
9776 
9777   Notes:
9778   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9779 
9780   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9781 
9782   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9783 
9784 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9785           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9786 @*/
9787 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9788 {
9789   PetscErrorCode (*f)(Mat, IS);
9790 
9791   PetscFunctionBegin;
9792   PetscValidType(mat, 1);
9793   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9794   PetscValidType(is, 2);
9795   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9796   PetscCheckSameComm(mat, 1, is, 2);
9797   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9798   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9799   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9800   PetscCall(MatDestroy(&mat->schur));
9801   PetscCall((*f)(mat, is));
9802   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9803   PetscFunctionReturn(PETSC_SUCCESS);
9804 }
9805 
9806 /*@
9807   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9808 
9809   Logically Collective
9810 
9811   Input Parameters:
9812 + F      - the factored matrix obtained by calling `MatGetFactor()`
9813 . S      - location where to return the Schur complement, can be `NULL`
9814 - status - the status of the Schur complement matrix, can be `NULL`
9815 
9816   Level: advanced
9817 
9818   Notes:
9819   You must call `MatFactorSetSchurIS()` before calling this routine.
9820 
9821   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9822 
9823   The routine provides a copy of the Schur matrix stored within the solver data structures.
9824   The caller must destroy the object when it is no longer needed.
9825   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9826 
9827   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)
9828 
9829   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9830 
9831   Developer Note:
9832   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9833   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9834 
9835 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9836 @*/
9837 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9838 {
9839   PetscFunctionBegin;
9840   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9841   if (S) PetscAssertPointer(S, 2);
9842   if (status) PetscAssertPointer(status, 3);
9843   if (S) {
9844     PetscErrorCode (*f)(Mat, Mat *);
9845 
9846     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9847     if (f) {
9848       PetscCall((*f)(F, S));
9849     } else {
9850       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9851     }
9852   }
9853   if (status) *status = F->schur_status;
9854   PetscFunctionReturn(PETSC_SUCCESS);
9855 }
9856 
9857 /*@
9858   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9859 
9860   Logically Collective
9861 
9862   Input Parameters:
9863 + F      - the factored matrix obtained by calling `MatGetFactor()`
9864 . S      - location where to return the Schur complement, can be `NULL`
9865 - status - the status of the Schur complement matrix, can be `NULL`
9866 
9867   Level: advanced
9868 
9869   Notes:
9870   You must call `MatFactorSetSchurIS()` before calling this routine.
9871 
9872   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9873 
9874   The routine returns a the Schur Complement stored within the data structures of the solver.
9875 
9876   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9877 
9878   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9879 
9880   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9881 
9882   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9883 
9884 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9885 @*/
9886 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9887 {
9888   PetscFunctionBegin;
9889   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9890   if (S) {
9891     PetscAssertPointer(S, 2);
9892     *S = F->schur;
9893   }
9894   if (status) {
9895     PetscAssertPointer(status, 3);
9896     *status = F->schur_status;
9897   }
9898   PetscFunctionReturn(PETSC_SUCCESS);
9899 }
9900 
9901 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9902 {
9903   Mat S = F->schur;
9904 
9905   PetscFunctionBegin;
9906   switch (F->schur_status) {
9907   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9908   case MAT_FACTOR_SCHUR_INVERTED:
9909     if (S) {
9910       S->ops->solve             = NULL;
9911       S->ops->matsolve          = NULL;
9912       S->ops->solvetranspose    = NULL;
9913       S->ops->matsolvetranspose = NULL;
9914       S->ops->solveadd          = NULL;
9915       S->ops->solvetransposeadd = NULL;
9916       S->factortype             = MAT_FACTOR_NONE;
9917       PetscCall(PetscFree(S->solvertype));
9918     }
9919   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9920     break;
9921   default:
9922     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9923   }
9924   PetscFunctionReturn(PETSC_SUCCESS);
9925 }
9926 
9927 /*@
9928   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9929 
9930   Logically Collective
9931 
9932   Input Parameters:
9933 + F      - the factored matrix obtained by calling `MatGetFactor()`
9934 . S      - location where the Schur complement is stored
9935 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9936 
9937   Level: advanced
9938 
9939 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9940 @*/
9941 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9942 {
9943   PetscFunctionBegin;
9944   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9945   if (S) {
9946     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9947     *S = NULL;
9948   }
9949   F->schur_status = status;
9950   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9951   PetscFunctionReturn(PETSC_SUCCESS);
9952 }
9953 
9954 /*@
9955   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9956 
9957   Logically Collective
9958 
9959   Input Parameters:
9960 + F   - the factored matrix obtained by calling `MatGetFactor()`
9961 . rhs - location where the right-hand side of the Schur complement system is stored
9962 - sol - location where the solution of the Schur complement system has to be returned
9963 
9964   Level: advanced
9965 
9966   Notes:
9967   The sizes of the vectors should match the size of the Schur complement
9968 
9969   Must be called after `MatFactorSetSchurIS()`
9970 
9971 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9972 @*/
9973 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9974 {
9975   PetscFunctionBegin;
9976   PetscValidType(F, 1);
9977   PetscValidType(rhs, 2);
9978   PetscValidType(sol, 3);
9979   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9980   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9981   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9982   PetscCheckSameComm(F, 1, rhs, 2);
9983   PetscCheckSameComm(F, 1, sol, 3);
9984   PetscCall(MatFactorFactorizeSchurComplement(F));
9985   switch (F->schur_status) {
9986   case MAT_FACTOR_SCHUR_FACTORED:
9987     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9988     break;
9989   case MAT_FACTOR_SCHUR_INVERTED:
9990     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9991     break;
9992   default:
9993     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9994   }
9995   PetscFunctionReturn(PETSC_SUCCESS);
9996 }
9997 
9998 /*@
9999   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
10000 
10001   Logically Collective
10002 
10003   Input Parameters:
10004 + F   - the factored matrix obtained by calling `MatGetFactor()`
10005 . rhs - location where the right-hand side of the Schur complement system is stored
10006 - sol - location where the solution of the Schur complement system has to be returned
10007 
10008   Level: advanced
10009 
10010   Notes:
10011   The sizes of the vectors should match the size of the Schur complement
10012 
10013   Must be called after `MatFactorSetSchurIS()`
10014 
10015 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
10016 @*/
10017 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
10018 {
10019   PetscFunctionBegin;
10020   PetscValidType(F, 1);
10021   PetscValidType(rhs, 2);
10022   PetscValidType(sol, 3);
10023   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10024   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
10025   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10026   PetscCheckSameComm(F, 1, rhs, 2);
10027   PetscCheckSameComm(F, 1, sol, 3);
10028   PetscCall(MatFactorFactorizeSchurComplement(F));
10029   switch (F->schur_status) {
10030   case MAT_FACTOR_SCHUR_FACTORED:
10031     PetscCall(MatSolve(F->schur, rhs, sol));
10032     break;
10033   case MAT_FACTOR_SCHUR_INVERTED:
10034     PetscCall(MatMult(F->schur, rhs, sol));
10035     break;
10036   default:
10037     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10038   }
10039   PetscFunctionReturn(PETSC_SUCCESS);
10040 }
10041 
10042 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
10043 #if PetscDefined(HAVE_CUDA)
10044 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
10045 #endif
10046 
10047 /* Schur status updated in the interface */
10048 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
10049 {
10050   Mat S = F->schur;
10051 
10052   PetscFunctionBegin;
10053   if (S) {
10054     PetscMPIInt size;
10055     PetscBool   isdense, isdensecuda;
10056 
10057     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10058     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10059     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10060     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10061     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10062     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10063     if (isdense) {
10064       PetscCall(MatSeqDenseInvertFactors_Private(S));
10065     } else if (isdensecuda) {
10066 #if defined(PETSC_HAVE_CUDA)
10067       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10068 #endif
10069     }
10070     // HIP??????????????
10071     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10072   }
10073   PetscFunctionReturn(PETSC_SUCCESS);
10074 }
10075 
10076 /*@
10077   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10078 
10079   Logically Collective
10080 
10081   Input Parameter:
10082 . F - the factored matrix obtained by calling `MatGetFactor()`
10083 
10084   Level: advanced
10085 
10086   Notes:
10087   Must be called after `MatFactorSetSchurIS()`.
10088 
10089   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10090 
10091 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10092 @*/
10093 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10094 {
10095   PetscFunctionBegin;
10096   PetscValidType(F, 1);
10097   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10098   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10099   PetscCall(MatFactorFactorizeSchurComplement(F));
10100   PetscCall(MatFactorInvertSchurComplement_Private(F));
10101   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10102   PetscFunctionReturn(PETSC_SUCCESS);
10103 }
10104 
10105 /*@
10106   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10107 
10108   Logically Collective
10109 
10110   Input Parameter:
10111 . F - the factored matrix obtained by calling `MatGetFactor()`
10112 
10113   Level: advanced
10114 
10115   Note:
10116   Must be called after `MatFactorSetSchurIS()`
10117 
10118 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10119 @*/
10120 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10121 {
10122   MatFactorInfo info;
10123 
10124   PetscFunctionBegin;
10125   PetscValidType(F, 1);
10126   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10127   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10128   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10129   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10130   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10131     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10132   } else {
10133     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10134   }
10135   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10136   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10137   PetscFunctionReturn(PETSC_SUCCESS);
10138 }
10139 
10140 /*@
10141   MatPtAP - Creates the matrix product $C = P^T * A * P$
10142 
10143   Neighbor-wise Collective
10144 
10145   Input Parameters:
10146 + A     - the matrix
10147 . P     - the projection matrix
10148 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10149 - 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
10150           if the result is a dense matrix this is irrelevant
10151 
10152   Output Parameter:
10153 . C - the product matrix
10154 
10155   Level: intermediate
10156 
10157   Notes:
10158   C will be created and must be destroyed by the user with `MatDestroy()`.
10159 
10160   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10161 
10162   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10163 
10164   Developer Note:
10165   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10166 
10167 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10168 @*/
10169 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10170 {
10171   PetscFunctionBegin;
10172   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10173   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10174 
10175   if (scall == MAT_INITIAL_MATRIX) {
10176     PetscCall(MatProductCreate(A, P, NULL, C));
10177     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10178     PetscCall(MatProductSetAlgorithm(*C, "default"));
10179     PetscCall(MatProductSetFill(*C, fill));
10180 
10181     (*C)->product->api_user = PETSC_TRUE;
10182     PetscCall(MatProductSetFromOptions(*C));
10183     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);
10184     PetscCall(MatProductSymbolic(*C));
10185   } else { /* scall == MAT_REUSE_MATRIX */
10186     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10187   }
10188 
10189   PetscCall(MatProductNumeric(*C));
10190   (*C)->symmetric = A->symmetric;
10191   (*C)->spd       = A->spd;
10192   PetscFunctionReturn(PETSC_SUCCESS);
10193 }
10194 
10195 /*@
10196   MatRARt - Creates the matrix product $C = R * A * R^T$
10197 
10198   Neighbor-wise Collective
10199 
10200   Input Parameters:
10201 + A     - the matrix
10202 . R     - the projection matrix
10203 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10204 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DETERMINE` or `PETSC_CURRENT` if you do not have a good estimate
10205           if the result is a dense matrix this is irrelevant
10206 
10207   Output Parameter:
10208 . C - the product matrix
10209 
10210   Level: intermediate
10211 
10212   Notes:
10213   `C` will be created and must be destroyed by the user with `MatDestroy()`.
10214 
10215   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10216 
10217   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10218   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10219   parallel `MatRARt()` is implemented via explicit transpose of `R`, which could be very expensive.
10220   We recommend using `MatPtAP()`.
10221 
10222   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10223 
10224 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10225 @*/
10226 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10227 {
10228   PetscFunctionBegin;
10229   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10230   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10231 
10232   if (scall == MAT_INITIAL_MATRIX) {
10233     PetscCall(MatProductCreate(A, R, NULL, C));
10234     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10235     PetscCall(MatProductSetAlgorithm(*C, "default"));
10236     PetscCall(MatProductSetFill(*C, fill));
10237 
10238     (*C)->product->api_user = PETSC_TRUE;
10239     PetscCall(MatProductSetFromOptions(*C));
10240     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);
10241     PetscCall(MatProductSymbolic(*C));
10242   } else { /* scall == MAT_REUSE_MATRIX */
10243     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10244   }
10245 
10246   PetscCall(MatProductNumeric(*C));
10247   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10248   PetscFunctionReturn(PETSC_SUCCESS);
10249 }
10250 
10251 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10252 {
10253   PetscBool flg = PETSC_TRUE;
10254 
10255   PetscFunctionBegin;
10256   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10257   if (scall == MAT_INITIAL_MATRIX) {
10258     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10259     PetscCall(MatProductCreate(A, B, NULL, C));
10260     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10261     PetscCall(MatProductSetFill(*C, fill));
10262   } else { /* scall == MAT_REUSE_MATRIX */
10263     Mat_Product *product = (*C)->product;
10264 
10265     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10266     if (flg && product && product->type != ptype) {
10267       PetscCall(MatProductClear(*C));
10268       product = NULL;
10269     }
10270     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10271     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10272       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10273       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10274       product        = (*C)->product;
10275       product->fill  = fill;
10276       product->clear = PETSC_TRUE;
10277     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10278       flg = PETSC_FALSE;
10279       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10280     }
10281   }
10282   if (flg) {
10283     (*C)->product->api_user = PETSC_TRUE;
10284     PetscCall(MatProductSetType(*C, ptype));
10285     PetscCall(MatProductSetFromOptions(*C));
10286     PetscCall(MatProductSymbolic(*C));
10287   }
10288   PetscCall(MatProductNumeric(*C));
10289   PetscFunctionReturn(PETSC_SUCCESS);
10290 }
10291 
10292 /*@
10293   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10294 
10295   Neighbor-wise Collective
10296 
10297   Input Parameters:
10298 + A     - the left matrix
10299 . B     - the right matrix
10300 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10301 - 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
10302           if the result is a dense matrix this is irrelevant
10303 
10304   Output Parameter:
10305 . C - the product matrix
10306 
10307   Notes:
10308   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10309 
10310   `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
10311   call to this function with `MAT_INITIAL_MATRIX`.
10312 
10313   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value actually needed.
10314 
10315   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`,
10316   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix `C` is sparse.
10317 
10318   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10319 
10320   Example of Usage:
10321 .vb
10322      MatProductCreate(A,B,NULL,&C);
10323      MatProductSetType(C,MATPRODUCT_AB);
10324      MatProductSymbolic(C);
10325      MatProductNumeric(C); // compute C=A * B
10326      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10327      MatProductNumeric(C);
10328      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10329      MatProductNumeric(C);
10330 .ve
10331 
10332   Level: intermediate
10333 
10334 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10335 @*/
10336 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10337 {
10338   PetscFunctionBegin;
10339   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10340   PetscFunctionReturn(PETSC_SUCCESS);
10341 }
10342 
10343 /*@
10344   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10345 
10346   Neighbor-wise Collective
10347 
10348   Input Parameters:
10349 + A     - the left matrix
10350 . B     - the right matrix
10351 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10352 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10353 
10354   Output Parameter:
10355 . C - the product matrix
10356 
10357   Options Database Key:
10358 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10359               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10360               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10361 
10362   Level: intermediate
10363 
10364   Notes:
10365   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10366 
10367   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10368 
10369   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10370   actually needed.
10371 
10372   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10373   and for pairs of `MATMPIDENSE` matrices.
10374 
10375   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10376 
10377   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10378 
10379 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10380 @*/
10381 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10382 {
10383   PetscFunctionBegin;
10384   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10385   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10386   PetscFunctionReturn(PETSC_SUCCESS);
10387 }
10388 
10389 /*@
10390   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10391 
10392   Neighbor-wise Collective
10393 
10394   Input Parameters:
10395 + A     - the left matrix
10396 . B     - the right matrix
10397 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10398 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DETERMINE` or `PETSC_CURRENT` if not known
10399 
10400   Output Parameter:
10401 . C - the product matrix
10402 
10403   Level: intermediate
10404 
10405   Notes:
10406   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10407 
10408   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10409 
10410   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10411 
10412   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10413   actually needed.
10414 
10415   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10416   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10417 
10418   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10419 
10420 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10421 @*/
10422 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10423 {
10424   PetscFunctionBegin;
10425   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10426   PetscFunctionReturn(PETSC_SUCCESS);
10427 }
10428 
10429 /*@
10430   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10431 
10432   Neighbor-wise Collective
10433 
10434   Input Parameters:
10435 + A     - the left matrix
10436 . B     - the middle matrix
10437 . C     - the right matrix
10438 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10439 - 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
10440           if the result is a dense matrix this is irrelevant
10441 
10442   Output Parameter:
10443 . D - the product matrix
10444 
10445   Level: intermediate
10446 
10447   Notes:
10448   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10449 
10450   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10451 
10452   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10453 
10454   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10455   actually needed.
10456 
10457   If you have many matrices with the same non-zero structure to multiply, you
10458   should use `MAT_REUSE_MATRIX` in all calls but the first
10459 
10460   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
10461 
10462 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10463 @*/
10464 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10465 {
10466   PetscFunctionBegin;
10467   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10468   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10469 
10470   if (scall == MAT_INITIAL_MATRIX) {
10471     PetscCall(MatProductCreate(A, B, C, D));
10472     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10473     PetscCall(MatProductSetAlgorithm(*D, "default"));
10474     PetscCall(MatProductSetFill(*D, fill));
10475 
10476     (*D)->product->api_user = PETSC_TRUE;
10477     PetscCall(MatProductSetFromOptions(*D));
10478     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,
10479                ((PetscObject)C)->type_name);
10480     PetscCall(MatProductSymbolic(*D));
10481   } else { /* user may change input matrices when REUSE */
10482     PetscCall(MatProductReplaceMats(A, B, C, *D));
10483   }
10484   PetscCall(MatProductNumeric(*D));
10485   PetscFunctionReturn(PETSC_SUCCESS);
10486 }
10487 
10488 /*@
10489   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10490 
10491   Collective
10492 
10493   Input Parameters:
10494 + mat      - the matrix
10495 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10496 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10497 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10498 
10499   Output Parameter:
10500 . matredundant - redundant matrix
10501 
10502   Level: advanced
10503 
10504   Notes:
10505   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10506   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10507 
10508   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10509   calling it.
10510 
10511   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10512 
10513 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10514 @*/
10515 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10516 {
10517   MPI_Comm       comm;
10518   PetscMPIInt    size;
10519   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10520   Mat_Redundant *redund     = NULL;
10521   PetscSubcomm   psubcomm   = NULL;
10522   MPI_Comm       subcomm_in = subcomm;
10523   Mat           *matseq;
10524   IS             isrow, iscol;
10525   PetscBool      newsubcomm = PETSC_FALSE;
10526 
10527   PetscFunctionBegin;
10528   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10529   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10530     PetscAssertPointer(*matredundant, 5);
10531     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10532   }
10533 
10534   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10535   if (size == 1 || nsubcomm == 1) {
10536     if (reuse == MAT_INITIAL_MATRIX) {
10537       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10538     } else {
10539       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");
10540       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10541     }
10542     PetscFunctionReturn(PETSC_SUCCESS);
10543   }
10544 
10545   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10546   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10547   MatCheckPreallocated(mat, 1);
10548 
10549   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10550   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10551     /* create psubcomm, then get subcomm */
10552     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10553     PetscCallMPI(MPI_Comm_size(comm, &size));
10554     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10555 
10556     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10557     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10558     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10559     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10560     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10561     newsubcomm = PETSC_TRUE;
10562     PetscCall(PetscSubcommDestroy(&psubcomm));
10563   }
10564 
10565   /* get isrow, iscol and a local sequential matrix matseq[0] */
10566   if (reuse == MAT_INITIAL_MATRIX) {
10567     mloc_sub = PETSC_DECIDE;
10568     nloc_sub = PETSC_DECIDE;
10569     if (bs < 1) {
10570       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10571       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10572     } else {
10573       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10574       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10575     }
10576     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10577     rstart = rend - mloc_sub;
10578     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10579     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10580     PetscCall(ISSetIdentity(iscol));
10581   } else { /* reuse == MAT_REUSE_MATRIX */
10582     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");
10583     /* retrieve subcomm */
10584     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10585     redund = (*matredundant)->redundant;
10586     isrow  = redund->isrow;
10587     iscol  = redund->iscol;
10588     matseq = redund->matseq;
10589   }
10590   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10591 
10592   /* get matredundant over subcomm */
10593   if (reuse == MAT_INITIAL_MATRIX) {
10594     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10595 
10596     /* create a supporting struct and attach it to C for reuse */
10597     PetscCall(PetscNew(&redund));
10598     (*matredundant)->redundant = redund;
10599     redund->isrow              = isrow;
10600     redund->iscol              = iscol;
10601     redund->matseq             = matseq;
10602     if (newsubcomm) {
10603       redund->subcomm = subcomm;
10604     } else {
10605       redund->subcomm = MPI_COMM_NULL;
10606     }
10607   } else {
10608     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10609   }
10610 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10611   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10612     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10613     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10614   }
10615 #endif
10616   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10617   PetscFunctionReturn(PETSC_SUCCESS);
10618 }
10619 
10620 /*@C
10621   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10622   a given `Mat`. Each submatrix can span multiple procs.
10623 
10624   Collective
10625 
10626   Input Parameters:
10627 + mat     - the matrix
10628 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10629 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10630 
10631   Output Parameter:
10632 . subMat - parallel sub-matrices each spanning a given `subcomm`
10633 
10634   Level: advanced
10635 
10636   Notes:
10637   The submatrix partition across processors is dictated by `subComm` a
10638   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10639   is not restricted to be grouped with consecutive original MPI processes.
10640 
10641   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10642   map directly to the layout of the original matrix [wrt the local
10643   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10644   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10645   the `subMat`. However the offDiagMat looses some columns - and this is
10646   reconstructed with `MatSetValues()`
10647 
10648   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10649 
10650 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10651 @*/
10652 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10653 {
10654   PetscMPIInt commsize, subCommSize;
10655 
10656   PetscFunctionBegin;
10657   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10658   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10659   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10660 
10661   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");
10662   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10663   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10664   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10665   PetscFunctionReturn(PETSC_SUCCESS);
10666 }
10667 
10668 /*@
10669   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10670 
10671   Not Collective
10672 
10673   Input Parameters:
10674 + mat   - matrix to extract local submatrix from
10675 . isrow - local row indices for submatrix
10676 - iscol - local column indices for submatrix
10677 
10678   Output Parameter:
10679 . submat - the submatrix
10680 
10681   Level: intermediate
10682 
10683   Notes:
10684   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10685 
10686   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10687   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10688 
10689   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10690   `MatSetValuesBlockedLocal()` will also be implemented.
10691 
10692   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10693   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10694 
10695 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10696 @*/
10697 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10698 {
10699   PetscFunctionBegin;
10700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10701   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10702   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10703   PetscCheckSameComm(isrow, 2, iscol, 3);
10704   PetscAssertPointer(submat, 4);
10705   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10706 
10707   if (mat->ops->getlocalsubmatrix) {
10708     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10709   } else {
10710     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10711   }
10712   PetscFunctionReturn(PETSC_SUCCESS);
10713 }
10714 
10715 /*@
10716   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10717 
10718   Not Collective
10719 
10720   Input Parameters:
10721 + mat    - matrix to extract local submatrix from
10722 . isrow  - local row indices for submatrix
10723 . iscol  - local column indices for submatrix
10724 - submat - the submatrix
10725 
10726   Level: intermediate
10727 
10728 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10729 @*/
10730 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10731 {
10732   PetscFunctionBegin;
10733   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10734   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10735   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10736   PetscCheckSameComm(isrow, 2, iscol, 3);
10737   PetscAssertPointer(submat, 4);
10738   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10739 
10740   if (mat->ops->restorelocalsubmatrix) {
10741     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10742   } else {
10743     PetscCall(MatDestroy(submat));
10744   }
10745   *submat = NULL;
10746   PetscFunctionReturn(PETSC_SUCCESS);
10747 }
10748 
10749 /*@
10750   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10751 
10752   Collective
10753 
10754   Input Parameter:
10755 . mat - the matrix
10756 
10757   Output Parameter:
10758 . is - if any rows have zero diagonals this contains the list of them
10759 
10760   Level: developer
10761 
10762 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10763 @*/
10764 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10765 {
10766   PetscFunctionBegin;
10767   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10768   PetscValidType(mat, 1);
10769   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10770   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10771 
10772   if (!mat->ops->findzerodiagonals) {
10773     Vec                diag;
10774     const PetscScalar *a;
10775     PetscInt          *rows;
10776     PetscInt           rStart, rEnd, r, nrow = 0;
10777 
10778     PetscCall(MatCreateVecs(mat, &diag, NULL));
10779     PetscCall(MatGetDiagonal(mat, diag));
10780     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10781     PetscCall(VecGetArrayRead(diag, &a));
10782     for (r = 0; r < rEnd - rStart; ++r)
10783       if (a[r] == 0.0) ++nrow;
10784     PetscCall(PetscMalloc1(nrow, &rows));
10785     nrow = 0;
10786     for (r = 0; r < rEnd - rStart; ++r)
10787       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10788     PetscCall(VecRestoreArrayRead(diag, &a));
10789     PetscCall(VecDestroy(&diag));
10790     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10791   } else {
10792     PetscUseTypeMethod(mat, findzerodiagonals, is);
10793   }
10794   PetscFunctionReturn(PETSC_SUCCESS);
10795 }
10796 
10797 /*@
10798   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10799 
10800   Collective
10801 
10802   Input Parameter:
10803 . mat - the matrix
10804 
10805   Output Parameter:
10806 . is - contains the list of rows with off block diagonal entries
10807 
10808   Level: developer
10809 
10810 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10811 @*/
10812 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10813 {
10814   PetscFunctionBegin;
10815   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10816   PetscValidType(mat, 1);
10817   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10818   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10819 
10820   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10821   PetscFunctionReturn(PETSC_SUCCESS);
10822 }
10823 
10824 /*@C
10825   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10826 
10827   Collective; No Fortran Support
10828 
10829   Input Parameter:
10830 . mat - the matrix
10831 
10832   Output Parameter:
10833 . values - the block inverses in column major order (FORTRAN-like)
10834 
10835   Level: advanced
10836 
10837   Notes:
10838   The size of the blocks is determined by the block size of the matrix.
10839 
10840   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10841 
10842   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10843 
10844 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10845 @*/
10846 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10847 {
10848   PetscFunctionBegin;
10849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10850   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10851   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10852   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10853   PetscFunctionReturn(PETSC_SUCCESS);
10854 }
10855 
10856 /*@
10857   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10858 
10859   Collective; No Fortran Support
10860 
10861   Input Parameters:
10862 + mat     - the matrix
10863 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10864 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10865 
10866   Output Parameter:
10867 . values - the block inverses in column major order (FORTRAN-like)
10868 
10869   Level: advanced
10870 
10871   Notes:
10872   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10873 
10874   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10875 
10876 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10877 @*/
10878 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10879 {
10880   PetscFunctionBegin;
10881   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10882   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10883   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10884   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10885   PetscFunctionReturn(PETSC_SUCCESS);
10886 }
10887 
10888 /*@
10889   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10890 
10891   Collective
10892 
10893   Input Parameters:
10894 + A - the matrix
10895 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10896 
10897   Level: advanced
10898 
10899   Note:
10900   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10901 
10902 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10903 @*/
10904 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10905 {
10906   const PetscScalar *vals;
10907   PetscInt          *dnnz;
10908   PetscInt           m, rstart, rend, bs, i, j;
10909 
10910   PetscFunctionBegin;
10911   PetscCall(MatInvertBlockDiagonal(A, &vals));
10912   PetscCall(MatGetBlockSize(A, &bs));
10913   PetscCall(MatGetLocalSize(A, &m, NULL));
10914   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10915   PetscCall(PetscMalloc1(m / bs, &dnnz));
10916   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10917   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10918   PetscCall(PetscFree(dnnz));
10919   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10920   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10921   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10922   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10923   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10924   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10925   PetscFunctionReturn(PETSC_SUCCESS);
10926 }
10927 
10928 /*@
10929   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10930   via `MatTransposeColoringCreate()`.
10931 
10932   Collective
10933 
10934   Input Parameter:
10935 . c - coloring context
10936 
10937   Level: intermediate
10938 
10939 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10940 @*/
10941 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10942 {
10943   MatTransposeColoring matcolor = *c;
10944 
10945   PetscFunctionBegin;
10946   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10947   if (--((PetscObject)matcolor)->refct > 0) {
10948     matcolor = NULL;
10949     PetscFunctionReturn(PETSC_SUCCESS);
10950   }
10951 
10952   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10953   PetscCall(PetscFree(matcolor->rows));
10954   PetscCall(PetscFree(matcolor->den2sp));
10955   PetscCall(PetscFree(matcolor->colorforcol));
10956   PetscCall(PetscFree(matcolor->columns));
10957   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10958   PetscCall(PetscHeaderDestroy(c));
10959   PetscFunctionReturn(PETSC_SUCCESS);
10960 }
10961 
10962 /*@
10963   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10964   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10965   `MatTransposeColoring` to sparse `B`.
10966 
10967   Collective
10968 
10969   Input Parameters:
10970 + coloring - coloring context created with `MatTransposeColoringCreate()`
10971 - B        - sparse matrix
10972 
10973   Output Parameter:
10974 . Btdense - dense matrix $B^T$
10975 
10976   Level: developer
10977 
10978   Note:
10979   These are used internally for some implementations of `MatRARt()`
10980 
10981 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10982 @*/
10983 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10984 {
10985   PetscFunctionBegin;
10986   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10987   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10988   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10989 
10990   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10991   PetscFunctionReturn(PETSC_SUCCESS);
10992 }
10993 
10994 /*@
10995   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10996   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10997   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10998   $C_{sp}$ from $C_{den}$.
10999 
11000   Collective
11001 
11002   Input Parameters:
11003 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
11004 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
11005 
11006   Output Parameter:
11007 . Csp - sparse matrix
11008 
11009   Level: developer
11010 
11011   Note:
11012   These are used internally for some implementations of `MatRARt()`
11013 
11014 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
11015 @*/
11016 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
11017 {
11018   PetscFunctionBegin;
11019   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
11020   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
11021   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
11022 
11023   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
11024   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
11025   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
11026   PetscFunctionReturn(PETSC_SUCCESS);
11027 }
11028 
11029 /*@
11030   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
11031 
11032   Collective
11033 
11034   Input Parameters:
11035 + mat        - the matrix product C
11036 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
11037 
11038   Output Parameter:
11039 . color - the new coloring context
11040 
11041   Level: intermediate
11042 
11043 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
11044           `MatTransColoringApplyDenToSp()`
11045 @*/
11046 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
11047 {
11048   MatTransposeColoring c;
11049   MPI_Comm             comm;
11050 
11051   PetscFunctionBegin;
11052   PetscAssertPointer(color, 3);
11053 
11054   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11055   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11056   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11057   c->ctype = iscoloring->ctype;
11058   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11059   *color = c;
11060   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11061   PetscFunctionReturn(PETSC_SUCCESS);
11062 }
11063 
11064 /*@
11065   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11066   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11067 
11068   Not Collective
11069 
11070   Input Parameter:
11071 . mat - the matrix
11072 
11073   Output Parameter:
11074 . state - the current state
11075 
11076   Level: intermediate
11077 
11078   Notes:
11079   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11080   different matrices
11081 
11082   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11083 
11084   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11085 
11086 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11087 @*/
11088 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11089 {
11090   PetscFunctionBegin;
11091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11092   *state = mat->nonzerostate;
11093   PetscFunctionReturn(PETSC_SUCCESS);
11094 }
11095 
11096 /*@
11097   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11098   matrices from each processor
11099 
11100   Collective
11101 
11102   Input Parameters:
11103 + comm   - the communicators the parallel matrix will live on
11104 . seqmat - the input sequential matrices
11105 . n      - number of local columns (or `PETSC_DECIDE`)
11106 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11107 
11108   Output Parameter:
11109 . mpimat - the parallel matrix generated
11110 
11111   Level: developer
11112 
11113   Note:
11114   The number of columns of the matrix in EACH processor MUST be the same.
11115 
11116 .seealso: [](ch_matrices), `Mat`
11117 @*/
11118 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11119 {
11120   PetscMPIInt size;
11121 
11122   PetscFunctionBegin;
11123   PetscCallMPI(MPI_Comm_size(comm, &size));
11124   if (size == 1) {
11125     if (reuse == MAT_INITIAL_MATRIX) {
11126       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11127     } else {
11128       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11129     }
11130     PetscFunctionReturn(PETSC_SUCCESS);
11131   }
11132 
11133   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");
11134 
11135   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11136   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11137   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11138   PetscFunctionReturn(PETSC_SUCCESS);
11139 }
11140 
11141 /*@
11142   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11143 
11144   Collective
11145 
11146   Input Parameters:
11147 + A - the matrix to create subdomains from
11148 - N - requested number of subdomains
11149 
11150   Output Parameters:
11151 + n   - number of subdomains resulting on this MPI process
11152 - iss - `IS` list with indices of subdomains on this MPI process
11153 
11154   Level: advanced
11155 
11156   Note:
11157   The number of subdomains must be smaller than the communicator size
11158 
11159 .seealso: [](ch_matrices), `Mat`, `IS`
11160 @*/
11161 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11162 {
11163   MPI_Comm    comm, subcomm;
11164   PetscMPIInt size, rank, color;
11165   PetscInt    rstart, rend, k;
11166 
11167   PetscFunctionBegin;
11168   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11169   PetscCallMPI(MPI_Comm_size(comm, &size));
11170   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11171   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);
11172   *n    = 1;
11173   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
11174   color = rank / k;
11175   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11176   PetscCall(PetscMalloc1(1, iss));
11177   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11178   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11179   PetscCallMPI(MPI_Comm_free(&subcomm));
11180   PetscFunctionReturn(PETSC_SUCCESS);
11181 }
11182 
11183 /*@
11184   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11185 
11186   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11187   If they are not the same, uses `MatMatMatMult()`.
11188 
11189   Once the coarse grid problem is constructed, correct for interpolation operators
11190   that are not of full rank, which can legitimately happen in the case of non-nested
11191   geometric multigrid.
11192 
11193   Input Parameters:
11194 + restrct     - restriction operator
11195 . dA          - fine grid matrix
11196 . interpolate - interpolation operator
11197 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11198 - fill        - expected fill, use `PETSC_DETERMINE` or `PETSC_DETERMINE` if you do not have a good estimate
11199 
11200   Output Parameter:
11201 . A - the Galerkin coarse matrix
11202 
11203   Options Database Key:
11204 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11205 
11206   Level: developer
11207 
11208   Note:
11209   The deprecated `PETSC_DEFAULT` in `fill` also means use the current value
11210 
11211 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11212 @*/
11213 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11214 {
11215   IS  zerorows;
11216   Vec diag;
11217 
11218   PetscFunctionBegin;
11219   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11220   /* Construct the coarse grid matrix */
11221   if (interpolate == restrct) {
11222     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11223   } else {
11224     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11225   }
11226 
11227   /* If the interpolation matrix is not of full rank, A will have zero rows.
11228      This can legitimately happen in the case of non-nested geometric multigrid.
11229      In that event, we set the rows of the matrix to the rows of the identity,
11230      ignoring the equations (as the RHS will also be zero). */
11231 
11232   PetscCall(MatFindZeroRows(*A, &zerorows));
11233 
11234   if (zerorows != NULL) { /* if there are any zero rows */
11235     PetscCall(MatCreateVecs(*A, &diag, NULL));
11236     PetscCall(MatGetDiagonal(*A, diag));
11237     PetscCall(VecISSet(diag, zerorows, 1.0));
11238     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11239     PetscCall(VecDestroy(&diag));
11240     PetscCall(ISDestroy(&zerorows));
11241   }
11242   PetscFunctionReturn(PETSC_SUCCESS);
11243 }
11244 
11245 /*@C
11246   MatSetOperation - Allows user to set a matrix operation for any matrix type
11247 
11248   Logically Collective
11249 
11250   Input Parameters:
11251 + mat - the matrix
11252 . op  - the name of the operation
11253 - f   - the function that provides the operation
11254 
11255   Level: developer
11256 
11257   Example Usage:
11258 .vb
11259   extern PetscErrorCode usermult(Mat, Vec, Vec);
11260 
11261   PetscCall(MatCreateXXX(comm, ..., &A));
11262   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11263 .ve
11264 
11265   Notes:
11266   See the file `include/petscmat.h` for a complete list of matrix
11267   operations, which all have the form MATOP_<OPERATION>, where
11268   <OPERATION> is the name (in all capital letters) of the
11269   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11270 
11271   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11272   sequence as the usual matrix interface routines, since they
11273   are intended to be accessed via the usual matrix interface
11274   routines, e.g.,
11275 .vb
11276   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11277 .ve
11278 
11279   In particular each function MUST return `PETSC_SUCCESS` on success and
11280   nonzero on failure.
11281 
11282   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11283 
11284 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11285 @*/
11286 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11287 {
11288   PetscFunctionBegin;
11289   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11290   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11291   (((void (**)(void))mat->ops)[op]) = f;
11292   PetscFunctionReturn(PETSC_SUCCESS);
11293 }
11294 
11295 /*@C
11296   MatGetOperation - Gets a matrix operation for any matrix type.
11297 
11298   Not Collective
11299 
11300   Input Parameters:
11301 + mat - the matrix
11302 - op  - the name of the operation
11303 
11304   Output Parameter:
11305 . f - the function that provides the operation
11306 
11307   Level: developer
11308 
11309   Example Usage:
11310 .vb
11311   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11312 
11313   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11314 .ve
11315 
11316   Notes:
11317   See the file include/petscmat.h for a complete list of matrix
11318   operations, which all have the form MATOP_<OPERATION>, where
11319   <OPERATION> is the name (in all capital letters) of the
11320   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11321 
11322   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11323 
11324 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11325 @*/
11326 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11327 {
11328   PetscFunctionBegin;
11329   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11330   *f = (((void (**)(void))mat->ops)[op]);
11331   PetscFunctionReturn(PETSC_SUCCESS);
11332 }
11333 
11334 /*@
11335   MatHasOperation - Determines whether the given matrix supports the particular operation.
11336 
11337   Not Collective
11338 
11339   Input Parameters:
11340 + mat - the matrix
11341 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11342 
11343   Output Parameter:
11344 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11345 
11346   Level: advanced
11347 
11348   Note:
11349   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11350 
11351 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11352 @*/
11353 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11354 {
11355   PetscFunctionBegin;
11356   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11357   PetscAssertPointer(has, 3);
11358   if (mat->ops->hasoperation) {
11359     PetscUseTypeMethod(mat, hasoperation, op, has);
11360   } else {
11361     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11362     else {
11363       *has = PETSC_FALSE;
11364       if (op == MATOP_CREATE_SUBMATRIX) {
11365         PetscMPIInt size;
11366 
11367         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11368         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11369       }
11370     }
11371   }
11372   PetscFunctionReturn(PETSC_SUCCESS);
11373 }
11374 
11375 /*@
11376   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11377 
11378   Collective
11379 
11380   Input Parameter:
11381 . mat - the matrix
11382 
11383   Output Parameter:
11384 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11385 
11386   Level: beginner
11387 
11388 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11389 @*/
11390 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11391 {
11392   PetscFunctionBegin;
11393   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11394   PetscValidType(mat, 1);
11395   PetscAssertPointer(cong, 2);
11396   if (!mat->rmap || !mat->cmap) {
11397     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11398     PetscFunctionReturn(PETSC_SUCCESS);
11399   }
11400   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11401     PetscCall(PetscLayoutSetUp(mat->rmap));
11402     PetscCall(PetscLayoutSetUp(mat->cmap));
11403     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11404     if (*cong) mat->congruentlayouts = 1;
11405     else mat->congruentlayouts = 0;
11406   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11407   PetscFunctionReturn(PETSC_SUCCESS);
11408 }
11409 
11410 PetscErrorCode MatSetInf(Mat A)
11411 {
11412   PetscFunctionBegin;
11413   PetscUseTypeMethod(A, setinf);
11414   PetscFunctionReturn(PETSC_SUCCESS);
11415 }
11416 
11417 /*@
11418   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
11419   and possibly removes small values from the graph structure.
11420 
11421   Collective
11422 
11423   Input Parameters:
11424 + A       - the matrix
11425 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11426 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11427 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11428 . num_idx - size of 'index' array
11429 - index   - array of block indices to use for graph strength of connection weight
11430 
11431   Output Parameter:
11432 . graph - the resulting graph
11433 
11434   Level: advanced
11435 
11436 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11437 @*/
11438 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11439 {
11440   PetscFunctionBegin;
11441   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11442   PetscValidType(A, 1);
11443   PetscValidLogicalCollectiveBool(A, scale, 3);
11444   PetscAssertPointer(graph, 7);
11445   PetscCall(PetscLogEventBegin(MAT_CreateGraph, A, 0, 0, 0));
11446   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11447   PetscCall(PetscLogEventEnd(MAT_CreateGraph, A, 0, 0, 0));
11448   PetscFunctionReturn(PETSC_SUCCESS);
11449 }
11450 
11451 /*@
11452   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11453   meaning the same memory is used for the matrix, and no new memory is allocated.
11454 
11455   Collective
11456 
11457   Input Parameters:
11458 + A    - the matrix
11459 - 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
11460 
11461   Level: intermediate
11462 
11463   Developer Note:
11464   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11465   of the arrays in the data structure are unneeded.
11466 
11467 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11468 @*/
11469 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11470 {
11471   PetscFunctionBegin;
11472   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11473   PetscUseTypeMethod(A, eliminatezeros, keep);
11474   PetscFunctionReturn(PETSC_SUCCESS);
11475 }
11476