xref: /petsc/src/mat/interface/matrix.c (revision f480ea8adbf1dd3c99486b786f1ca135091665c8) !
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU, MAT_HIPCopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51   MatSetRandom - Sets all components of a matrix to random numbers.
52 
53   Logically Collective
54 
55   Input Parameters:
56 + x    - the matrix
57 - rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60   Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67   Level: intermediate
68 
69   Notes:
70   For sparse matrices that have been preallocated but not been assembled, it randomly selects appropriate locations,
71 
72   for sparse matrices that already have nonzero locations, it fills the locations with random numbers.
73 
74   It generates an error if used on unassembled sparse matrices that have not been preallocated.
75 
76 .seealso: [](ch_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107   MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109   Logically Collective
110 
111   Input Parameter:
112 . mat - the factored matrix
113 
114   Output Parameters:
115 + pivot - the pivot value computed
116 - row   - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119   Level: advanced
120 
121   Notes:
122   This routine does not work for factorizations done with external packages.
123 
124   This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`,
129 `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`,
130 `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscAssertPointer(pivot, 2);
137   PetscAssertPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144   MatFactorGetError - gets the error code from a factorization
145 
146   Logically Collective
147 
148   Input Parameter:
149 . mat - the factored matrix
150 
151   Output Parameter:
152 . err - the error code
153 
154   Level: advanced
155 
156   Note:
157   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
160           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscAssertPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172   MatFactorClearError - clears the error code in a factorization
173 
174   Logically Collective
175 
176   Input Parameter:
177 . mat - the factored matrix
178 
179   Level: developer
180 
181   Note:
182   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n, st;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetOwnershipRange(mat, &st, NULL));
207     PetscCall(MatGetSize(mat, &N, NULL));
208     PetscCall(MatGetLocalSize(mat, &n, NULL));
209     PetscCall(VecSet(l, 0.0));
210     PetscCall(VecSetRandom(r, NULL));
211     PetscCall(MatMult(mat, r, l));
212     PetscCall(VecGetArrayRead(l, &al));
213   } else { /* nonzero columns */
214     PetscCall(MatGetOwnershipRangeColumn(mat, &st, NULL));
215     PetscCall(MatGetSize(mat, NULL, &N));
216     PetscCall(MatGetLocalSize(mat, NULL, &n));
217     PetscCall(VecSet(r, 0.0));
218     PetscCall(VecSetRandom(l, NULL));
219     PetscCall(MatMultTranspose(mat, l, r));
220     PetscCall(VecGetArrayRead(r, &al));
221   }
222   if (tol <= 0.0) {
223     for (i = 0, nz = 0; i < n; i++)
224       if (al[i] != 0.0) nz++;
225   } else {
226     for (i = 0, nz = 0; i < n; i++)
227       if (PetscAbsScalar(al[i]) > tol) nz++;
228   }
229   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
230   if (gnz != N) {
231     PetscInt *nzr;
232     PetscCall(PetscMalloc1(nz, &nzr));
233     if (nz) {
234       if (tol < 0) {
235         for (i = 0, nz = 0; i < n; i++)
236           if (al[i] != 0.0) nzr[nz++] = i + st;
237       } else {
238         for (i = 0, nz = 0; i < n; i++)
239           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i + st;
240       }
241     }
242     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
243   } else *nonzero = NULL;
244   if (!cols) { /* nonzero rows */
245     PetscCall(VecRestoreArrayRead(l, &al));
246   } else {
247     PetscCall(VecRestoreArrayRead(r, &al));
248   }
249   PetscCall(VecDestroy(&l));
250   PetscCall(VecDestroy(&r));
251   PetscFunctionReturn(PETSC_SUCCESS);
252 }
253 
254 /*@
255   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
256 
257   Input Parameter:
258 . mat - the matrix
259 
260   Output Parameter:
261 . keptrows - the rows that are not completely zero
262 
263   Level: intermediate
264 
265   Note:
266   `keptrows` is set to `NULL` if all rows are nonzero.
267 
268   Developer Note:
269   If `keptrows` is not `NULL`, it must be sorted.
270 
271 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
272  @*/
273 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
274 {
275   PetscFunctionBegin;
276   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
277   PetscValidType(mat, 1);
278   PetscAssertPointer(keptrows, 2);
279   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
280   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
281   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
282   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
283   if (keptrows && *keptrows) PetscCall(ISSetInfo(*keptrows, IS_SORTED, IS_GLOBAL, PETSC_FALSE, PETSC_TRUE));
284   PetscFunctionReturn(PETSC_SUCCESS);
285 }
286 
287 /*@
288   MatFindZeroRows - Locate all rows that are completely zero in the matrix
289 
290   Input Parameter:
291 . mat - the matrix
292 
293   Output Parameter:
294 . zerorows - the rows that are completely zero
295 
296   Level: intermediate
297 
298   Note:
299   `zerorows` is set to `NULL` if no rows are zero.
300 
301 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
302  @*/
303 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
304 {
305   IS       keptrows;
306   PetscInt m, n;
307 
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
310   PetscValidType(mat, 1);
311   PetscAssertPointer(zerorows, 2);
312   PetscCall(MatFindNonzeroRows(mat, &keptrows));
313   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
314      In keeping with this convention, we set zerorows to NULL if there are no zero
315      rows. */
316   if (keptrows == NULL) {
317     *zerorows = NULL;
318   } else {
319     PetscCall(MatGetOwnershipRange(mat, &m, &n));
320     PetscCall(ISComplement(keptrows, m, n, zerorows));
321     PetscCall(ISDestroy(&keptrows));
322   }
323   PetscFunctionReturn(PETSC_SUCCESS);
324 }
325 
326 /*@
327   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
328 
329   Not Collective
330 
331   Input Parameter:
332 . A - the matrix
333 
334   Output Parameter:
335 . a - the diagonal part (which is a SEQUENTIAL matrix)
336 
337   Level: advanced
338 
339   Notes:
340   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
341 
342   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
343 
344 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
345 @*/
346 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
347 {
348   PetscFunctionBegin;
349   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
350   PetscValidType(A, 1);
351   PetscAssertPointer(a, 2);
352   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
353   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
354   else {
355     PetscMPIInt size;
356 
357     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
358     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
359     *a = A;
360   }
361   PetscFunctionReturn(PETSC_SUCCESS);
362 }
363 
364 /*@
365   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
366 
367   Collective
368 
369   Input Parameter:
370 . mat - the matrix
371 
372   Output Parameter:
373 . trace - the sum of the diagonal entries
374 
375   Level: advanced
376 
377 .seealso: [](ch_matrices), `Mat`
378 @*/
379 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
380 {
381   Vec diag;
382 
383   PetscFunctionBegin;
384   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
385   PetscAssertPointer(trace, 2);
386   PetscCall(MatCreateVecs(mat, &diag, NULL));
387   PetscCall(MatGetDiagonal(mat, diag));
388   PetscCall(VecSum(diag, trace));
389   PetscCall(VecDestroy(&diag));
390   PetscFunctionReturn(PETSC_SUCCESS);
391 }
392 
393 /*@
394   MatRealPart - Zeros out the imaginary part of the matrix
395 
396   Logically Collective
397 
398   Input Parameter:
399 . mat - the matrix
400 
401   Level: advanced
402 
403 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
404 @*/
405 PetscErrorCode MatRealPart(Mat mat)
406 {
407   PetscFunctionBegin;
408   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
409   PetscValidType(mat, 1);
410   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
411   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
412   MatCheckPreallocated(mat, 1);
413   PetscUseTypeMethod(mat, realpart);
414   PetscFunctionReturn(PETSC_SUCCESS);
415 }
416 
417 /*@C
418   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
419 
420   Collective
421 
422   Input Parameter:
423 . mat - the matrix
424 
425   Output Parameters:
426 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
427 - ghosts  - the global indices of the ghost points
428 
429   Level: advanced
430 
431   Note:
432   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
433 
434 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
435 @*/
436 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
437 {
438   PetscFunctionBegin;
439   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
440   PetscValidType(mat, 1);
441   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
442   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
443   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
444   else {
445     if (nghosts) *nghosts = 0;
446     if (ghosts) *ghosts = NULL;
447   }
448   PetscFunctionReturn(PETSC_SUCCESS);
449 }
450 
451 /*@
452   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
453 
454   Logically Collective
455 
456   Input Parameter:
457 . mat - the matrix
458 
459   Level: advanced
460 
461 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
462 @*/
463 PetscErrorCode MatImaginaryPart(Mat mat)
464 {
465   PetscFunctionBegin;
466   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
467   PetscValidType(mat, 1);
468   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
469   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
470   MatCheckPreallocated(mat, 1);
471   PetscUseTypeMethod(mat, imaginarypart);
472   PetscFunctionReturn(PETSC_SUCCESS);
473 }
474 
475 /*@
476   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
477 
478   Not Collective
479 
480   Input Parameter:
481 . mat - the matrix
482 
483   Output Parameters:
484 + missing - is any diagonal entry missing
485 - dd      - first diagonal entry that is missing (optional) on this process
486 
487   Level: advanced
488 
489   Note:
490   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
491 
492 .seealso: [](ch_matrices), `Mat`
493 @*/
494 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
495 {
496   PetscFunctionBegin;
497   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
498   PetscValidType(mat, 1);
499   PetscAssertPointer(missing, 2);
500   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
501   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
502   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
503   PetscFunctionReturn(PETSC_SUCCESS);
504 }
505 
506 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
507 /*@C
508   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
509   for each row that you get to ensure that your application does
510   not bleed memory.
511 
512   Not Collective
513 
514   Input Parameters:
515 + mat - the matrix
516 - row - the row to get
517 
518   Output Parameters:
519 + ncols - if not `NULL`, the number of nonzeros in `row`
520 . cols  - if not `NULL`, the column numbers
521 - vals  - if not `NULL`, the numerical values
522 
523   Level: advanced
524 
525   Notes:
526   This routine is provided for people who need to have direct access
527   to the structure of a matrix.  We hope that we provide enough
528   high-level matrix routines that few users will need it.
529 
530   `MatGetRow()` always returns 0-based column indices, regardless of
531   whether the internal representation is 0-based (default) or 1-based.
532 
533   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
534   not wish to extract these quantities.
535 
536   The user can only examine the values extracted with `MatGetRow()`;
537   the values CANNOT be altered.  To change the matrix entries, one
538   must use `MatSetValues()`.
539 
540   You can only have one call to `MatGetRow()` outstanding for a particular
541   matrix at a time, per processor. `MatGetRow()` can only obtain rows
542   associated with the given processor, it cannot get rows from the
543   other processors; for that we suggest using `MatCreateSubMatrices()`, then
544   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
545   is in the global number of rows.
546 
547   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
548 
549   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
550 
551   Fortran Note:
552   The calling sequence is
553 .vb
554    MatGetRow(matrix,row,ncols,cols,values,ierr)
555          Mat         matrix (input)
556          PetscInt    row    (input)
557          PetscInt    ncols  (output)
558          PetscInt    cols(maxcols) (output)
559          PetscScalar values(maxcols) output
560 .ve
561   where maxcols >= maximum nonzeros in any row of the matrix.
562 
563 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
564 @*/
565 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
566 {
567   PetscInt incols;
568 
569   PetscFunctionBegin;
570   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
571   PetscValidType(mat, 1);
572   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
573   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
574   MatCheckPreallocated(mat, 1);
575   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
576   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
577   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
578   if (ncols) *ncols = incols;
579   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
580   PetscFunctionReturn(PETSC_SUCCESS);
581 }
582 
583 /*@
584   MatConjugate - replaces the matrix values with their complex conjugates
585 
586   Logically Collective
587 
588   Input Parameter:
589 . mat - the matrix
590 
591   Level: advanced
592 
593 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
594 @*/
595 PetscErrorCode MatConjugate(Mat mat)
596 {
597   PetscFunctionBegin;
598   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
599   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
600   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
601     PetscUseTypeMethod(mat, conjugate);
602     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
603   }
604   PetscFunctionReturn(PETSC_SUCCESS);
605 }
606 
607 /*@C
608   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
609 
610   Not Collective
611 
612   Input Parameters:
613 + mat   - the matrix
614 . row   - the row to get
615 . ncols - the number of nonzeros
616 . cols  - the columns of the nonzeros
617 - vals  - if nonzero the column values
618 
619   Level: advanced
620 
621   Notes:
622   This routine should be called after you have finished examining the entries.
623 
624   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
625   us of the array after it has been restored. If you pass `NULL`, it will
626   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
627 
628   Fortran Note:
629   `MatRestoreRow()` MUST be called after `MatGetRow()`
630   before another call to `MatGetRow()` can be made.
631 
632 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
633 @*/
634 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
635 {
636   PetscFunctionBegin;
637   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
638   if (ncols) PetscAssertPointer(ncols, 3);
639   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
640   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
641   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
642   if (ncols) *ncols = 0;
643   if (cols) *cols = NULL;
644   if (vals) *vals = NULL;
645   PetscFunctionReturn(PETSC_SUCCESS);
646 }
647 
648 /*@
649   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
650   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
651 
652   Not Collective
653 
654   Input Parameter:
655 . mat - the matrix
656 
657   Level: advanced
658 
659   Note:
660   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.
661 
662 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
663 @*/
664 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
665 {
666   PetscFunctionBegin;
667   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
668   PetscValidType(mat, 1);
669   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
670   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
671   MatCheckPreallocated(mat, 1);
672   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
673   PetscUseTypeMethod(mat, getrowuppertriangular);
674   PetscFunctionReturn(PETSC_SUCCESS);
675 }
676 
677 /*@
678   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
679 
680   Not Collective
681 
682   Input Parameter:
683 . mat - the matrix
684 
685   Level: advanced
686 
687   Note:
688   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
689 
690 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
691 @*/
692 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
693 {
694   PetscFunctionBegin;
695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
696   PetscValidType(mat, 1);
697   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
698   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
699   MatCheckPreallocated(mat, 1);
700   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
701   PetscUseTypeMethod(mat, restorerowuppertriangular);
702   PetscFunctionReturn(PETSC_SUCCESS);
703 }
704 
705 /*@
706   MatSetOptionsPrefix - Sets the prefix used for searching for all
707   `Mat` options in the database.
708 
709   Logically Collective
710 
711   Input Parameters:
712 + A      - the matrix
713 - prefix - the prefix to prepend to all option names
714 
715   Level: advanced
716 
717   Notes:
718   A hyphen (-) must NOT be given at the beginning of the prefix name.
719   The first character of all runtime options is AUTOMATICALLY the hyphen.
720 
721   This is NOT used for options for the factorization of the matrix. Normally the
722   prefix is automatically passed in from the PC calling the factorization. To set
723   it directly use  `MatSetOptionsPrefixFactor()`
724 
725 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
726 @*/
727 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
728 {
729   PetscFunctionBegin;
730   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
731   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
732   PetscFunctionReturn(PETSC_SUCCESS);
733 }
734 
735 /*@
736   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
737   for matrices created with `MatGetFactor()`
738 
739   Logically Collective
740 
741   Input Parameters:
742 + A      - the matrix
743 - prefix - the prefix to prepend to all option names for the factored matrix
744 
745   Level: developer
746 
747   Notes:
748   A hyphen (-) must NOT be given at the beginning of the prefix name.
749   The first character of all runtime options is AUTOMATICALLY the hyphen.
750 
751   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
752   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
753 
754 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
755 @*/
756 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
757 {
758   PetscFunctionBegin;
759   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
760   if (prefix) {
761     PetscAssertPointer(prefix, 2);
762     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
763     if (prefix != A->factorprefix) {
764       PetscCall(PetscFree(A->factorprefix));
765       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
766     }
767   } else PetscCall(PetscFree(A->factorprefix));
768   PetscFunctionReturn(PETSC_SUCCESS);
769 }
770 
771 /*@
772   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
773   for matrices created with `MatGetFactor()`
774 
775   Logically Collective
776 
777   Input Parameters:
778 + A      - the matrix
779 - prefix - the prefix to prepend to all option names for the factored matrix
780 
781   Level: developer
782 
783   Notes:
784   A hyphen (-) must NOT be given at the beginning of the prefix name.
785   The first character of all runtime options is AUTOMATICALLY the hyphen.
786 
787   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
788   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
789 
790 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
791           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
792           `MatSetOptionsPrefix()`
793 @*/
794 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
795 {
796   size_t len1, len2, new_len;
797 
798   PetscFunctionBegin;
799   PetscValidHeader(A, 1);
800   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
801   if (!A->factorprefix) {
802     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
803     PetscFunctionReturn(PETSC_SUCCESS);
804   }
805   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
806 
807   PetscCall(PetscStrlen(A->factorprefix, &len1));
808   PetscCall(PetscStrlen(prefix, &len2));
809   new_len = len1 + len2 + 1;
810   PetscCall(PetscRealloc(new_len * sizeof(*A->factorprefix), &A->factorprefix));
811   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
812   PetscFunctionReturn(PETSC_SUCCESS);
813 }
814 
815 /*@
816   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
817   matrix options in the database.
818 
819   Logically Collective
820 
821   Input Parameters:
822 + A      - the matrix
823 - prefix - the prefix to prepend to all option names
824 
825   Level: advanced
826 
827   Note:
828   A hyphen (-) must NOT be given at the beginning of the prefix name.
829   The first character of all runtime options is AUTOMATICALLY the hyphen.
830 
831 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
832 @*/
833 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
834 {
835   PetscFunctionBegin;
836   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
837   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
838   PetscFunctionReturn(PETSC_SUCCESS);
839 }
840 
841 /*@
842   MatGetOptionsPrefix - Gets the prefix used for searching for all
843   matrix options in the database.
844 
845   Not Collective
846 
847   Input Parameter:
848 . A - the matrix
849 
850   Output Parameter:
851 . prefix - pointer to the prefix string used
852 
853   Level: advanced
854 
855   Fortran Note:
856   The user should pass in a string `prefix` of
857   sufficient length to hold the prefix.
858 
859 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
860 @*/
861 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
862 {
863   PetscFunctionBegin;
864   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
865   PetscAssertPointer(prefix, 2);
866   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
867   PetscFunctionReturn(PETSC_SUCCESS);
868 }
869 
870 /*@
871   MatGetState - Gets the state of a `Mat`. Same value as returned by `PetscObjectStateGet()`
872 
873   Not Collective
874 
875   Input Parameter:
876 . A - the matrix
877 
878   Output Parameter:
879 . state - the object state
880 
881   Level: advanced
882 
883   Note:
884   Object state is an integer which gets increased every time
885   the object is changed. By saving and later querying the object state
886   one can determine whether information about the object is still current.
887 
888   See `MatGetNonzeroState()` to determine if the nonzero structure of the matrix has changed.
889 
890 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PetscObjectStateGet()`, `MatGetNonzeroState()`
891 @*/
892 PetscErrorCode MatGetState(Mat A, PetscObjectState *state)
893 {
894   PetscFunctionBegin;
895   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
896   PetscAssertPointer(state, 2);
897   PetscCall(PetscObjectStateGet((PetscObject)A, state));
898   PetscFunctionReturn(PETSC_SUCCESS);
899 }
900 
901 /*@
902   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user.
903 
904   Collective
905 
906   Input Parameter:
907 . A - the matrix
908 
909   Level: beginner
910 
911   Notes:
912   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
913 
914   Users can reset the preallocation to access the original memory.
915 
916   Currently only supported for  `MATAIJ` matrices.
917 
918 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
919 @*/
920 PetscErrorCode MatResetPreallocation(Mat A)
921 {
922   PetscFunctionBegin;
923   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
924   PetscValidType(A, 1);
925   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()");
926   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
927   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
928   PetscFunctionReturn(PETSC_SUCCESS);
929 }
930 
931 /*@
932   MatSetUp - Sets up the internal matrix data structures for later use.
933 
934   Collective
935 
936   Input Parameter:
937 . A - the matrix
938 
939   Level: intermediate
940 
941   Notes:
942   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
943   setting values in the matrix.
944 
945   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
946 
947 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
948 @*/
949 PetscErrorCode MatSetUp(Mat A)
950 {
951   PetscFunctionBegin;
952   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
953   if (!((PetscObject)A)->type_name) {
954     PetscMPIInt size;
955 
956     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
957     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
958   }
959   if (!A->preallocated) PetscTryTypeMethod(A, setup);
960   PetscCall(PetscLayoutSetUp(A->rmap));
961   PetscCall(PetscLayoutSetUp(A->cmap));
962   A->preallocated = PETSC_TRUE;
963   PetscFunctionReturn(PETSC_SUCCESS);
964 }
965 
966 #if defined(PETSC_HAVE_SAWS)
967   #include <petscviewersaws.h>
968 #endif
969 
970 /*
971    If threadsafety is on extraneous matrices may be printed
972 
973    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
974 */
975 #if !defined(PETSC_HAVE_THREADSAFETY)
976 static PetscInt insidematview = 0;
977 #endif
978 
979 /*@
980   MatViewFromOptions - View properties of the matrix based on options set in the options database
981 
982   Collective
983 
984   Input Parameters:
985 + A    - the matrix
986 . obj  - optional additional object that provides the options prefix to use
987 - name - command line option
988 
989   Options Database Key:
990 . -mat_view [viewertype]:... - the viewer and its options
991 
992   Level: intermediate
993 
994   Note:
995 .vb
996     If no value is provided ascii:stdout is used
997        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
998                                                   for example ascii::ascii_info prints just the information about the object not all details
999                                                   unless :append is given filename opens in write mode, overwriting what was already there
1000        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
1001        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
1002        socket[:port]                             defaults to the standard output port
1003        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
1004 .ve
1005 
1006 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
1007 @*/
1008 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
1009 {
1010   PetscFunctionBegin;
1011   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
1012 #if !defined(PETSC_HAVE_THREADSAFETY)
1013   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
1014 #endif
1015   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
1016   PetscFunctionReturn(PETSC_SUCCESS);
1017 }
1018 
1019 /*@
1020   MatView - display information about a matrix in a variety ways
1021 
1022   Collective on viewer
1023 
1024   Input Parameters:
1025 + mat    - the matrix
1026 - viewer - visualization context
1027 
1028   Options Database Keys:
1029 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1030 . -mat_view ::ascii_info_detail    - Prints more detailed info
1031 . -mat_view                        - Prints matrix in ASCII format
1032 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1033 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1034 . -display <name>                  - Sets display name (default is host)
1035 . -draw_pause <sec>                - Sets number of seconds to pause after display
1036 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1037 . -viewer_socket_machine <machine> - -
1038 . -viewer_socket_port <port>       - -
1039 . -mat_view binary                 - save matrix to file in binary format
1040 - -viewer_binary_filename <name>   - -
1041 
1042   Level: beginner
1043 
1044   Notes:
1045   The available visualization contexts include
1046 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1047 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1048 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1049 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1050 
1051   The user can open alternative visualization contexts with
1052 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1053 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1054   specified file; corresponding input uses `MatLoad()`
1055 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1056   an X window display
1057 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1058   Currently only the `MATSEQDENSE` and `MATAIJ`
1059   matrix types support the Socket viewer.
1060 
1061   The user can call `PetscViewerPushFormat()` to specify the output
1062   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1063   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1064 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1065 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1066 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1067 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1068   format common among all matrix types
1069 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1070   format (which is in many cases the same as the default)
1071 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1072   size and structure (not the matrix entries)
1073 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1074   the matrix structure
1075 
1076   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1077   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1078 
1079   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1080 
1081   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1082   viewer is used.
1083 
1084   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1085   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1086 
1087   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1088   and then use the following mouse functions.
1089 .vb
1090   left mouse: zoom in
1091   middle mouse: zoom out
1092   right mouse: continue with the simulation
1093 .ve
1094 
1095 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1096           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1097 @*/
1098 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1099 {
1100   PetscInt          rows, cols, rbs, cbs;
1101   PetscBool         isascii, isstring, issaws;
1102   PetscViewerFormat format;
1103   PetscMPIInt       size;
1104 
1105   PetscFunctionBegin;
1106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1107   PetscValidType(mat, 1);
1108   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1109   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1110 
1111   PetscCall(PetscViewerGetFormat(viewer, &format));
1112   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)viewer), &size));
1113   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1114 
1115 #if !defined(PETSC_HAVE_THREADSAFETY)
1116   insidematview++;
1117 #endif
1118   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1119   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1120   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1121   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");
1122 
1123   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1124   if (isascii) {
1125     if (!mat->preallocated) {
1126       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1127 #if !defined(PETSC_HAVE_THREADSAFETY)
1128       insidematview--;
1129 #endif
1130       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1131       PetscFunctionReturn(PETSC_SUCCESS);
1132     }
1133     if (!mat->assembled) {
1134       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1135 #if !defined(PETSC_HAVE_THREADSAFETY)
1136       insidematview--;
1137 #endif
1138       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1139       PetscFunctionReturn(PETSC_SUCCESS);
1140     }
1141     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1142     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1143       MatNullSpace nullsp, transnullsp;
1144 
1145       PetscCall(PetscViewerASCIIPushTab(viewer));
1146       PetscCall(MatGetSize(mat, &rows, &cols));
1147       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1148       if (rbs != 1 || cbs != 1) {
1149         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" : ""));
1150         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1151       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1152       if (mat->factortype) {
1153         MatSolverType solver;
1154         PetscCall(MatFactorGetSolverType(mat, &solver));
1155         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1156       }
1157       if (mat->ops->getinfo) {
1158         MatInfo info;
1159         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1160         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1161         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1162       }
1163       PetscCall(MatGetNullSpace(mat, &nullsp));
1164       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1165       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1166       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1167       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1168       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1169       PetscCall(PetscViewerASCIIPushTab(viewer));
1170       PetscCall(MatProductView(mat, viewer));
1171       PetscCall(PetscViewerASCIIPopTab(viewer));
1172       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1173         IS tmp;
1174 
1175         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)viewer), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1176         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1177         PetscCall(PetscViewerASCIIPushTab(viewer));
1178         PetscCall(ISView(tmp, viewer));
1179         PetscCall(PetscViewerASCIIPopTab(viewer));
1180         PetscCall(ISDestroy(&tmp));
1181       }
1182     }
1183   } else if (issaws) {
1184 #if defined(PETSC_HAVE_SAWS)
1185     PetscMPIInt rank;
1186 
1187     PetscCall(PetscObjectName((PetscObject)mat));
1188     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1189     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1190 #endif
1191   } else if (isstring) {
1192     const char *type;
1193     PetscCall(MatGetType(mat, &type));
1194     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1195     PetscTryTypeMethod(mat, view, viewer);
1196   }
1197   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1198     PetscCall(PetscViewerASCIIPushTab(viewer));
1199     PetscUseTypeMethod(mat, viewnative, viewer);
1200     PetscCall(PetscViewerASCIIPopTab(viewer));
1201   } else if (mat->ops->view) {
1202     PetscCall(PetscViewerASCIIPushTab(viewer));
1203     PetscUseTypeMethod(mat, view, viewer);
1204     PetscCall(PetscViewerASCIIPopTab(viewer));
1205   }
1206   if (isascii) {
1207     PetscCall(PetscViewerGetFormat(viewer, &format));
1208     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1209   }
1210   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1211 #if !defined(PETSC_HAVE_THREADSAFETY)
1212   insidematview--;
1213 #endif
1214   PetscFunctionReturn(PETSC_SUCCESS);
1215 }
1216 
1217 #if defined(PETSC_USE_DEBUG)
1218   #include <../src/sys/totalview/tv_data_display.h>
1219 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1220 {
1221   TV_add_row("Local rows", "int", &mat->rmap->n);
1222   TV_add_row("Local columns", "int", &mat->cmap->n);
1223   TV_add_row("Global rows", "int", &mat->rmap->N);
1224   TV_add_row("Global columns", "int", &mat->cmap->N);
1225   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1226   return TV_format_OK;
1227 }
1228 #endif
1229 
1230 /*@
1231   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1232   with `MatView()`.  The matrix format is determined from the options database.
1233   Generates a parallel MPI matrix if the communicator has more than one
1234   processor.  The default matrix type is `MATAIJ`.
1235 
1236   Collective
1237 
1238   Input Parameters:
1239 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1240             or some related function before a call to `MatLoad()`
1241 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1242 
1243   Options Database Key:
1244 . -matload_block_size <bs> - set block size
1245 
1246   Level: beginner
1247 
1248   Notes:
1249   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1250   `Mat` before calling this routine if you wish to set it from the options database.
1251 
1252   `MatLoad()` automatically loads into the options database any options
1253   given in the file filename.info where filename is the name of the file
1254   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1255   file will be ignored if you use the -viewer_binary_skip_info option.
1256 
1257   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1258   sets the default matrix type AIJ and sets the local and global sizes.
1259   If type and/or size is already set, then the same are used.
1260 
1261   In parallel, each processor can load a subset of rows (or the
1262   entire matrix).  This routine is especially useful when a large
1263   matrix is stored on disk and only part of it is desired on each
1264   processor.  For example, a parallel solver may access only some of
1265   the rows from each processor.  The algorithm used here reads
1266   relatively small blocks of data rather than reading the entire
1267   matrix and then subsetting it.
1268 
1269   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1270   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1271   or the sequence like
1272 .vb
1273     `PetscViewer` v;
1274     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1275     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1276     `PetscViewerSetFromOptions`(v);
1277     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1278     `PetscViewerFileSetName`(v,"datafile");
1279 .ve
1280   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1281 $ -viewer_type {binary, hdf5}
1282 
1283   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1284   and src/mat/tutorials/ex10.c with the second approach.
1285 
1286   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1287   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1288   Multiple objects, both matrices and vectors, can be stored within the same file.
1289   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1290 
1291   Most users should not need to know the details of the binary storage
1292   format, since `MatLoad()` and `MatView()` completely hide these details.
1293   But for anyone who is interested, the standard binary matrix storage
1294   format is
1295 
1296 .vb
1297     PetscInt    MAT_FILE_CLASSID
1298     PetscInt    number of rows
1299     PetscInt    number of columns
1300     PetscInt    total number of nonzeros
1301     PetscInt    *number nonzeros in each row
1302     PetscInt    *column indices of all nonzeros (starting index is zero)
1303     PetscScalar *values of all nonzeros
1304 .ve
1305   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1306   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
1307   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1308 
1309   PETSc automatically does the byte swapping for
1310   machines that store the bytes reversed. Thus if you write your own binary
1311   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1312   and `PetscBinaryWrite()` to see how this may be done.
1313 
1314   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1315   Each processor's chunk is loaded independently by its owning MPI process.
1316   Multiple objects, both matrices and vectors, can be stored within the same file.
1317   They are looked up by their PetscObject name.
1318 
1319   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1320   by default the same structure and naming of the AIJ arrays and column count
1321   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1322 $    save example.mat A b -v7.3
1323   can be directly read by this routine (see Reference 1 for details).
1324 
1325   Depending on your MATLAB version, this format might be a default,
1326   otherwise you can set it as default in Preferences.
1327 
1328   Unless -nocompression flag is used to save the file in MATLAB,
1329   PETSc must be configured with ZLIB package.
1330 
1331   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1332 
1333   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1334 
1335   Corresponding `MatView()` is not yet implemented.
1336 
1337   The loaded matrix is actually a transpose of the original one in MATLAB,
1338   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1339   With this format, matrix is automatically transposed by PETSc,
1340   unless the matrix is marked as SPD or symmetric
1341   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1342 
1343   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1344 
1345 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1346  @*/
1347 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1348 {
1349   PetscBool flg;
1350 
1351   PetscFunctionBegin;
1352   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1353   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1354 
1355   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1356 
1357   flg = PETSC_FALSE;
1358   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1359   if (flg) {
1360     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1361     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1362   }
1363   flg = PETSC_FALSE;
1364   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1365   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1366 
1367   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1368   PetscUseTypeMethod(mat, load, viewer);
1369   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1370   PetscFunctionReturn(PETSC_SUCCESS);
1371 }
1372 
1373 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1374 {
1375   Mat_Redundant *redund = *redundant;
1376 
1377   PetscFunctionBegin;
1378   if (redund) {
1379     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1380       PetscCall(ISDestroy(&redund->isrow));
1381       PetscCall(ISDestroy(&redund->iscol));
1382       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1383     } else {
1384       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1385       PetscCall(PetscFree(redund->sbuf_j));
1386       PetscCall(PetscFree(redund->sbuf_a));
1387       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1388         PetscCall(PetscFree(redund->rbuf_j[i]));
1389         PetscCall(PetscFree(redund->rbuf_a[i]));
1390       }
1391       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1392     }
1393 
1394     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1395     PetscCall(PetscFree(redund));
1396   }
1397   PetscFunctionReturn(PETSC_SUCCESS);
1398 }
1399 
1400 /*@
1401   MatDestroy - Frees space taken by a matrix.
1402 
1403   Collective
1404 
1405   Input Parameter:
1406 . A - the matrix
1407 
1408   Level: beginner
1409 
1410   Developer Note:
1411   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1412   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1413   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1414   if changes are needed here.
1415 
1416 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1417 @*/
1418 PetscErrorCode MatDestroy(Mat *A)
1419 {
1420   PetscFunctionBegin;
1421   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1422   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1423   if (--((PetscObject)*A)->refct > 0) {
1424     *A = NULL;
1425     PetscFunctionReturn(PETSC_SUCCESS);
1426   }
1427 
1428   /* if memory was published with SAWs then destroy it */
1429   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1430   PetscTryTypeMethod(*A, destroy);
1431 
1432   PetscCall(PetscFree((*A)->factorprefix));
1433   PetscCall(PetscFree((*A)->defaultvectype));
1434   PetscCall(PetscFree((*A)->defaultrandtype));
1435   PetscCall(PetscFree((*A)->bsizes));
1436   PetscCall(PetscFree((*A)->solvertype));
1437   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1438   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1439   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1440   PetscCall(MatProductClear(*A));
1441   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1442   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1443   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1444   PetscCall(MatDestroy(&(*A)->schur));
1445   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1446   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1447   PetscCall(PetscHeaderDestroy(A));
1448   PetscFunctionReturn(PETSC_SUCCESS);
1449 }
1450 
1451 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1452 /*@
1453   MatSetValues - Inserts or adds a block of values into a matrix.
1454   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1455   MUST be called after all calls to `MatSetValues()` have been completed.
1456 
1457   Not Collective
1458 
1459   Input Parameters:
1460 + mat  - the matrix
1461 . v    - a logically two-dimensional array of values
1462 . m    - the number of rows
1463 . idxm - the global indices of the rows
1464 . n    - the number of columns
1465 . idxn - the global indices of the columns
1466 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1467 
1468   Level: beginner
1469 
1470   Notes:
1471   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1472 
1473   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1474   options cannot be mixed without intervening calls to the assembly
1475   routines.
1476 
1477   `MatSetValues()` uses 0-based row and column numbers in Fortran
1478   as well as in C.
1479 
1480   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1481   simply ignored. This allows easily inserting element stiffness matrices
1482   with homogeneous Dirichlet boundary conditions that you don't want represented
1483   in the matrix.
1484 
1485   Efficiency Alert:
1486   The routine `MatSetValuesBlocked()` may offer much better efficiency
1487   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1488 
1489   Fortran Notes:
1490   If any of `idxm`, `idxn`, and `v` are scalars pass them using, for example,
1491 .vb
1492   MatSetValues(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
1493 .ve
1494 
1495   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
1496 
1497   Developer Note:
1498   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1499   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1500 
1501 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1502           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1503 @*/
1504 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1505 {
1506   PetscFunctionBeginHot;
1507   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1508   PetscValidType(mat, 1);
1509   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1510   PetscAssertPointer(idxm, 3);
1511   PetscAssertPointer(idxn, 5);
1512   MatCheckPreallocated(mat, 1);
1513 
1514   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1515   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1516 
1517   if (PetscDefined(USE_DEBUG)) {
1518     PetscInt i, j;
1519 
1520     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1521     if (v) {
1522       for (i = 0; i < m; i++) {
1523         for (j = 0; j < n; j++) {
1524           if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1525 #if defined(PETSC_USE_COMPLEX)
1526             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]);
1527 #else
1528             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]);
1529 #endif
1530         }
1531       }
1532     }
1533     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);
1534     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);
1535   }
1536 
1537   if (mat->assembled) {
1538     mat->was_assembled = PETSC_TRUE;
1539     mat->assembled     = PETSC_FALSE;
1540   }
1541   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1542   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1543   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1544   PetscFunctionReturn(PETSC_SUCCESS);
1545 }
1546 
1547 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1548 /*@
1549   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1550   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1551   MUST be called after all calls to `MatSetValues()` have been completed.
1552 
1553   Not Collective
1554 
1555   Input Parameters:
1556 + mat  - the matrix
1557 . v    - a logically two-dimensional array of values
1558 . ism  - the rows to provide
1559 . isn  - the columns to provide
1560 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1561 
1562   Level: beginner
1563 
1564   Notes:
1565   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1566 
1567   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1568   options cannot be mixed without intervening calls to the assembly
1569   routines.
1570 
1571   `MatSetValues()` uses 0-based row and column numbers in Fortran
1572   as well as in C.
1573 
1574   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1575   simply ignored. This allows easily inserting element stiffness matrices
1576   with homogeneous Dirichlet boundary conditions that you don't want represented
1577   in the matrix.
1578 
1579   Efficiency Alert:
1580   The routine `MatSetValuesBlocked()` may offer much better efficiency
1581   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1582 
1583   This is currently not optimized for any particular `ISType`
1584 
1585   Developer Note:
1586   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1587   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1588 
1589 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1590           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1591 @*/
1592 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1593 {
1594   PetscInt        m, n;
1595   const PetscInt *rows, *cols;
1596 
1597   PetscFunctionBeginHot;
1598   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1599   PetscCall(ISGetIndices(ism, &rows));
1600   PetscCall(ISGetIndices(isn, &cols));
1601   PetscCall(ISGetLocalSize(ism, &m));
1602   PetscCall(ISGetLocalSize(isn, &n));
1603   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1604   PetscCall(ISRestoreIndices(ism, &rows));
1605   PetscCall(ISRestoreIndices(isn, &cols));
1606   PetscFunctionReturn(PETSC_SUCCESS);
1607 }
1608 
1609 /*@
1610   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1611   values into a matrix
1612 
1613   Not Collective
1614 
1615   Input Parameters:
1616 + mat - the matrix
1617 . row - the (block) row to set
1618 - v   - a logically two-dimensional array of values
1619 
1620   Level: intermediate
1621 
1622   Notes:
1623   The values, `v`, are column-oriented (for the block version) and sorted
1624 
1625   All the nonzero values in `row` must be provided
1626 
1627   The matrix must have previously had its column indices set, likely by having been assembled.
1628 
1629   `row` must belong to this MPI process
1630 
1631 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1632           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1633 @*/
1634 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1635 {
1636   PetscInt globalrow;
1637 
1638   PetscFunctionBegin;
1639   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1640   PetscValidType(mat, 1);
1641   PetscAssertPointer(v, 3);
1642   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1643   PetscCall(MatSetValuesRow(mat, globalrow, v));
1644   PetscFunctionReturn(PETSC_SUCCESS);
1645 }
1646 
1647 /*@
1648   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1649   values into a matrix
1650 
1651   Not Collective
1652 
1653   Input Parameters:
1654 + mat - the matrix
1655 . row - the (block) row to set
1656 - 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
1657 
1658   Level: advanced
1659 
1660   Notes:
1661   The values, `v`, are column-oriented for the block version.
1662 
1663   All the nonzeros in `row` must be provided
1664 
1665   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1666 
1667   `row` must belong to this process
1668 
1669 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1670           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1671 @*/
1672 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1673 {
1674   PetscFunctionBeginHot;
1675   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1676   PetscValidType(mat, 1);
1677   MatCheckPreallocated(mat, 1);
1678   PetscAssertPointer(v, 3);
1679   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1680   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1681   mat->insertmode = INSERT_VALUES;
1682 
1683   if (mat->assembled) {
1684     mat->was_assembled = PETSC_TRUE;
1685     mat->assembled     = PETSC_FALSE;
1686   }
1687   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1688   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1689   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1690   PetscFunctionReturn(PETSC_SUCCESS);
1691 }
1692 
1693 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1694 /*@
1695   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1696   Using structured grid indexing
1697 
1698   Not Collective
1699 
1700   Input Parameters:
1701 + mat  - the matrix
1702 . m    - number of rows being entered
1703 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1704 . n    - number of columns being entered
1705 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1706 . v    - a logically two-dimensional array of values
1707 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1708 
1709   Level: beginner
1710 
1711   Notes:
1712   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1713 
1714   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1715   options cannot be mixed without intervening calls to the assembly
1716   routines.
1717 
1718   The grid coordinates are across the entire grid, not just the local portion
1719 
1720   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1721   as well as in C.
1722 
1723   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1724 
1725   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1726   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1727 
1728   The columns and rows in the stencil passed in MUST be contained within the
1729   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1730   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1731   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1732   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1733 
1734   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1735   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1736   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1737   `DM_BOUNDARY_PERIODIC` boundary type.
1738 
1739   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
1740   a single value per point) you can skip filling those indices.
1741 
1742   Inspired by the structured grid interface to the HYPRE package
1743   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1744 
1745   Efficiency Alert:
1746   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1747   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1748 
1749   Fortran Note:
1750   `idxm` and `idxn` should be declared as
1751 $     MatStencil idxm(4,m),idxn(4,n)
1752   and the values inserted using
1753 .vb
1754     idxm(MatStencil_i,1) = i
1755     idxm(MatStencil_j,1) = j
1756     idxm(MatStencil_k,1) = k
1757     idxm(MatStencil_c,1) = c
1758     etc
1759 .ve
1760 
1761 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1762           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1763 @*/
1764 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1765 {
1766   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1767   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1768   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1769 
1770   PetscFunctionBegin;
1771   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1772   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1773   PetscValidType(mat, 1);
1774   PetscAssertPointer(idxm, 3);
1775   PetscAssertPointer(idxn, 5);
1776 
1777   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1778     jdxm = buf;
1779     jdxn = buf + m;
1780   } else {
1781     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1782     jdxm = bufm;
1783     jdxn = bufn;
1784   }
1785   for (i = 0; i < m; i++) {
1786     for (j = 0; j < 3 - sdim; j++) dxm++;
1787     tmp = *dxm++ - starts[0];
1788     for (j = 0; j < dim - 1; j++) {
1789       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1790       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1791     }
1792     if (mat->stencil.noc) dxm++;
1793     jdxm[i] = tmp;
1794   }
1795   for (i = 0; i < n; i++) {
1796     for (j = 0; j < 3 - sdim; j++) dxn++;
1797     tmp = *dxn++ - starts[0];
1798     for (j = 0; j < dim - 1; j++) {
1799       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1800       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1801     }
1802     if (mat->stencil.noc) dxn++;
1803     jdxn[i] = tmp;
1804   }
1805   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1806   PetscCall(PetscFree2(bufm, bufn));
1807   PetscFunctionReturn(PETSC_SUCCESS);
1808 }
1809 
1810 /*@
1811   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1812   Using structured grid indexing
1813 
1814   Not Collective
1815 
1816   Input Parameters:
1817 + mat  - the matrix
1818 . m    - number of rows being entered
1819 . idxm - grid coordinates for matrix rows being entered
1820 . n    - number of columns being entered
1821 . idxn - grid coordinates for matrix columns being entered
1822 . v    - a logically two-dimensional array of values
1823 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1824 
1825   Level: beginner
1826 
1827   Notes:
1828   By default the values, `v`, are row-oriented and unsorted.
1829   See `MatSetOption()` for other options.
1830 
1831   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1832   options cannot be mixed without intervening calls to the assembly
1833   routines.
1834 
1835   The grid coordinates are across the entire grid, not just the local portion
1836 
1837   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1838   as well as in C.
1839 
1840   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1841 
1842   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1843   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1844 
1845   The columns and rows in the stencil passed in MUST be contained within the
1846   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1847   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1848   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1849   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1850 
1851   Negative indices may be passed in idxm and idxn, these rows and columns are
1852   simply ignored. This allows easily inserting element stiffness matrices
1853   with homogeneous Dirichlet boundary conditions that you don't want represented
1854   in the matrix.
1855 
1856   Inspired by the structured grid interface to the HYPRE package
1857   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1858 
1859   Fortran Note:
1860   `idxm` and `idxn` should be declared as
1861 $     MatStencil idxm(4,m),idxn(4,n)
1862   and the values inserted using
1863 .vb
1864     idxm(MatStencil_i,1) = i
1865     idxm(MatStencil_j,1) = j
1866     idxm(MatStencil_k,1) = k
1867    etc
1868 .ve
1869 
1870 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1871           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1872           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1873 @*/
1874 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1875 {
1876   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1877   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1878   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1879 
1880   PetscFunctionBegin;
1881   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1882   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1883   PetscValidType(mat, 1);
1884   PetscAssertPointer(idxm, 3);
1885   PetscAssertPointer(idxn, 5);
1886   PetscAssertPointer(v, 6);
1887 
1888   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1889     jdxm = buf;
1890     jdxn = buf + m;
1891   } else {
1892     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1893     jdxm = bufm;
1894     jdxn = bufn;
1895   }
1896   for (i = 0; i < m; i++) {
1897     for (j = 0; j < 3 - sdim; j++) dxm++;
1898     tmp = *dxm++ - starts[0];
1899     for (j = 0; j < sdim - 1; j++) {
1900       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1901       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1902     }
1903     dxm++;
1904     jdxm[i] = tmp;
1905   }
1906   for (i = 0; i < n; i++) {
1907     for (j = 0; j < 3 - sdim; j++) dxn++;
1908     tmp = *dxn++ - starts[0];
1909     for (j = 0; j < sdim - 1; j++) {
1910       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1911       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1912     }
1913     dxn++;
1914     jdxn[i] = tmp;
1915   }
1916   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1917   PetscCall(PetscFree2(bufm, bufn));
1918   PetscFunctionReturn(PETSC_SUCCESS);
1919 }
1920 
1921 /*@
1922   MatSetStencil - Sets the grid information for setting values into a matrix via
1923   `MatSetValuesStencil()`
1924 
1925   Not Collective
1926 
1927   Input Parameters:
1928 + mat    - the matrix
1929 . dim    - dimension of the grid 1, 2, or 3
1930 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1931 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1932 - dof    - number of degrees of freedom per node
1933 
1934   Level: beginner
1935 
1936   Notes:
1937   Inspired by the structured grid interface to the HYPRE package
1938   (www.llnl.gov/CASC/hyper)
1939 
1940   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1941   user.
1942 
1943 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1944           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1945 @*/
1946 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1947 {
1948   PetscFunctionBegin;
1949   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1950   PetscAssertPointer(dims, 3);
1951   PetscAssertPointer(starts, 4);
1952 
1953   mat->stencil.dim = dim + (dof > 1);
1954   for (PetscInt i = 0; i < dim; i++) {
1955     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1956     mat->stencil.starts[i] = starts[dim - i - 1];
1957   }
1958   mat->stencil.dims[dim]   = dof;
1959   mat->stencil.starts[dim] = 0;
1960   mat->stencil.noc         = (PetscBool)(dof == 1);
1961   PetscFunctionReturn(PETSC_SUCCESS);
1962 }
1963 
1964 /*@
1965   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1966 
1967   Not Collective
1968 
1969   Input Parameters:
1970 + mat  - the matrix
1971 . v    - a logically two-dimensional array of values
1972 . m    - the number of block rows
1973 . idxm - the global block indices
1974 . n    - the number of block columns
1975 . idxn - the global block indices
1976 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1977 
1978   Level: intermediate
1979 
1980   Notes:
1981   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1982   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1983 
1984   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1985   NOT the total number of rows/columns; for example, if the block size is 2 and
1986   you are passing in values for rows 2,3,4,5  then `m` would be 2 (not 4).
1987   The values in `idxm` would be 1 2; that is the first index for each block divided by
1988   the block size.
1989 
1990   You must call `MatSetBlockSize()` when constructing this matrix (before
1991   preallocating it).
1992 
1993   By default the values, `v`, are row-oriented, so the layout of
1994   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1995 
1996   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1997   options cannot be mixed without intervening calls to the assembly
1998   routines.
1999 
2000   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
2001   as well as in C.
2002 
2003   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
2004   simply ignored. This allows easily inserting element stiffness matrices
2005   with homogeneous Dirichlet boundary conditions that you don't want represented
2006   in the matrix.
2007 
2008   Each time an entry is set within a sparse matrix via `MatSetValues()`,
2009   internal searching must be done to determine where to place the
2010   data in the matrix storage space.  By instead inserting blocks of
2011   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
2012   reduced.
2013 
2014   Example:
2015 .vb
2016    Suppose m=n=2 and block size(bs) = 2 The array is
2017 
2018    1  2  | 3  4
2019    5  6  | 7  8
2020    - - - | - - -
2021    9  10 | 11 12
2022    13 14 | 15 16
2023 
2024    v[] should be passed in like
2025    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
2026 
2027   If you are not using row-oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
2028    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
2029 .ve
2030 
2031   Fortran Notes:
2032   If any of `idmx`, `idxn`, and `v` are scalars pass them using, for example,
2033 .vb
2034   MatSetValuesBlocked(mat, one, [idxm], one, [idxn], [v], INSERT_VALUES)
2035 .ve
2036 
2037   If `v` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2038 
2039 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
2040 @*/
2041 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2042 {
2043   PetscFunctionBeginHot;
2044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2045   PetscValidType(mat, 1);
2046   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2047   PetscAssertPointer(idxm, 3);
2048   PetscAssertPointer(idxn, 5);
2049   MatCheckPreallocated(mat, 1);
2050   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2051   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2052   if (PetscDefined(USE_DEBUG)) {
2053     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2054     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2055   }
2056   if (PetscDefined(USE_DEBUG)) {
2057     PetscInt rbs, cbs, M, N, i;
2058     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2059     PetscCall(MatGetSize(mat, &M, &N));
2060     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);
2061     for (i = 0; i < n; i++)
2062       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);
2063   }
2064   if (mat->assembled) {
2065     mat->was_assembled = PETSC_TRUE;
2066     mat->assembled     = PETSC_FALSE;
2067   }
2068   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2069   if (mat->ops->setvaluesblocked) {
2070     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2071   } else {
2072     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2073     PetscInt i, j, bs, cbs;
2074 
2075     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2076     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2077       iidxm = buf;
2078       iidxn = buf + m * bs;
2079     } else {
2080       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2081       iidxm = bufr;
2082       iidxn = bufc;
2083     }
2084     for (i = 0; i < m; i++) {
2085       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2086     }
2087     if (m != n || bs != cbs || idxm != idxn) {
2088       for (i = 0; i < n; i++) {
2089         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2090       }
2091     } else iidxn = iidxm;
2092     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2093     PetscCall(PetscFree2(bufr, bufc));
2094   }
2095   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2096   PetscFunctionReturn(PETSC_SUCCESS);
2097 }
2098 
2099 /*@
2100   MatGetValues - Gets a block of local values from a matrix.
2101 
2102   Not Collective; can only return values that are owned by the give process
2103 
2104   Input Parameters:
2105 + mat  - the matrix
2106 . v    - a logically two-dimensional array for storing the values
2107 . m    - the number of rows
2108 . idxm - the  global indices of the rows
2109 . n    - the number of columns
2110 - idxn - the global indices of the columns
2111 
2112   Level: advanced
2113 
2114   Notes:
2115   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2116   The values, `v`, are then returned in a row-oriented format,
2117   analogous to that used by default in `MatSetValues()`.
2118 
2119   `MatGetValues()` uses 0-based row and column numbers in
2120   Fortran as well as in C.
2121 
2122   `MatGetValues()` requires that the matrix has been assembled
2123   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2124   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2125   without intermediate matrix assembly.
2126 
2127   Negative row or column indices will be ignored and those locations in `v` will be
2128   left unchanged.
2129 
2130   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2131   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2132   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2133 
2134 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2135 @*/
2136 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2137 {
2138   PetscFunctionBegin;
2139   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2140   PetscValidType(mat, 1);
2141   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2142   PetscAssertPointer(idxm, 3);
2143   PetscAssertPointer(idxn, 5);
2144   PetscAssertPointer(v, 6);
2145   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2146   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2147   MatCheckPreallocated(mat, 1);
2148 
2149   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2150   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2151   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2152   PetscFunctionReturn(PETSC_SUCCESS);
2153 }
2154 
2155 /*@
2156   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2157   defined previously by `MatSetLocalToGlobalMapping()`
2158 
2159   Not Collective
2160 
2161   Input Parameters:
2162 + mat  - the matrix
2163 . nrow - number of rows
2164 . irow - the row local indices
2165 . ncol - number of columns
2166 - icol - the column local indices
2167 
2168   Output Parameter:
2169 . y - a logically two-dimensional array of values
2170 
2171   Level: advanced
2172 
2173   Notes:
2174   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2175 
2176   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,
2177   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2178   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2179   with `MatSetLocalToGlobalMapping()`.
2180 
2181   Developer Note:
2182   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2183   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2184 
2185 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2186           `MatSetValuesLocal()`, `MatGetValues()`
2187 @*/
2188 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2189 {
2190   PetscFunctionBeginHot;
2191   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2192   PetscValidType(mat, 1);
2193   MatCheckPreallocated(mat, 1);
2194   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2195   PetscAssertPointer(irow, 3);
2196   PetscAssertPointer(icol, 5);
2197   if (PetscDefined(USE_DEBUG)) {
2198     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2199     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2200   }
2201   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2202   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2203   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2204   else {
2205     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2206     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2207       irowm = buf;
2208       icolm = buf + nrow;
2209     } else {
2210       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2211       irowm = bufr;
2212       icolm = bufc;
2213     }
2214     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2215     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2216     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2217     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2218     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2219     PetscCall(PetscFree2(bufr, bufc));
2220   }
2221   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2222   PetscFunctionReturn(PETSC_SUCCESS);
2223 }
2224 
2225 /*@
2226   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2227   the same size. Currently, this can only be called once and creates the given matrix.
2228 
2229   Not Collective
2230 
2231   Input Parameters:
2232 + mat  - the matrix
2233 . nb   - the number of blocks
2234 . bs   - the number of rows (and columns) in each block
2235 . rows - a concatenation of the rows for each block
2236 - v    - a concatenation of logically two-dimensional arrays of values
2237 
2238   Level: advanced
2239 
2240   Notes:
2241   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2242 
2243   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2244 
2245 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2246           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2247 @*/
2248 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2249 {
2250   PetscFunctionBegin;
2251   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2252   PetscValidType(mat, 1);
2253   PetscAssertPointer(rows, 4);
2254   PetscAssertPointer(v, 5);
2255   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2256 
2257   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2258   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2259   else {
2260     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2261   }
2262   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2263   PetscFunctionReturn(PETSC_SUCCESS);
2264 }
2265 
2266 /*@
2267   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2268   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2269   using a local (per-processor) numbering.
2270 
2271   Not Collective
2272 
2273   Input Parameters:
2274 + x        - the matrix
2275 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2276 - cmapping - column mapping
2277 
2278   Level: intermediate
2279 
2280   Note:
2281   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2282 
2283 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2284 @*/
2285 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2286 {
2287   PetscFunctionBegin;
2288   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2289   PetscValidType(x, 1);
2290   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2291   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2292   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2293   else {
2294     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2295     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2296   }
2297   PetscFunctionReturn(PETSC_SUCCESS);
2298 }
2299 
2300 /*@
2301   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2302 
2303   Not Collective
2304 
2305   Input Parameter:
2306 . A - the matrix
2307 
2308   Output Parameters:
2309 + rmapping - row mapping
2310 - cmapping - column mapping
2311 
2312   Level: advanced
2313 
2314 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2315 @*/
2316 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2317 {
2318   PetscFunctionBegin;
2319   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2320   PetscValidType(A, 1);
2321   if (rmapping) {
2322     PetscAssertPointer(rmapping, 2);
2323     *rmapping = A->rmap->mapping;
2324   }
2325   if (cmapping) {
2326     PetscAssertPointer(cmapping, 3);
2327     *cmapping = A->cmap->mapping;
2328   }
2329   PetscFunctionReturn(PETSC_SUCCESS);
2330 }
2331 
2332 /*@
2333   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2334 
2335   Logically Collective
2336 
2337   Input Parameters:
2338 + A    - the matrix
2339 . rmap - row layout
2340 - cmap - column layout
2341 
2342   Level: advanced
2343 
2344   Note:
2345   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2346 
2347 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2348 @*/
2349 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2350 {
2351   PetscFunctionBegin;
2352   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2353   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2354   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2355   PetscFunctionReturn(PETSC_SUCCESS);
2356 }
2357 
2358 /*@
2359   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2360 
2361   Not Collective
2362 
2363   Input Parameter:
2364 . A - the matrix
2365 
2366   Output Parameters:
2367 + rmap - row layout
2368 - cmap - column layout
2369 
2370   Level: advanced
2371 
2372 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2373 @*/
2374 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2375 {
2376   PetscFunctionBegin;
2377   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2378   PetscValidType(A, 1);
2379   if (rmap) {
2380     PetscAssertPointer(rmap, 2);
2381     *rmap = A->rmap;
2382   }
2383   if (cmap) {
2384     PetscAssertPointer(cmap, 3);
2385     *cmap = A->cmap;
2386   }
2387   PetscFunctionReturn(PETSC_SUCCESS);
2388 }
2389 
2390 /*@
2391   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2392   using a local numbering of the rows and columns.
2393 
2394   Not Collective
2395 
2396   Input Parameters:
2397 + mat  - the matrix
2398 . nrow - number of rows
2399 . irow - the row local indices
2400 . ncol - number of columns
2401 . icol - the column local indices
2402 . y    - a logically two-dimensional array of values
2403 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2404 
2405   Level: intermediate
2406 
2407   Notes:
2408   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2409 
2410   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2411   options cannot be mixed without intervening calls to the assembly
2412   routines.
2413 
2414   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2415   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2416 
2417   Fortran Notes:
2418   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2419 .vb
2420   MatSetValuesLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2421 .ve
2422 
2423   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2424 
2425   Developer Note:
2426   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2427   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2428 
2429 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2430           `MatGetValuesLocal()`
2431 @*/
2432 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2433 {
2434   PetscFunctionBeginHot;
2435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2436   PetscValidType(mat, 1);
2437   MatCheckPreallocated(mat, 1);
2438   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2439   PetscAssertPointer(irow, 3);
2440   PetscAssertPointer(icol, 5);
2441   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2442   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2443   if (PetscDefined(USE_DEBUG)) {
2444     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2445     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2446   }
2447 
2448   if (mat->assembled) {
2449     mat->was_assembled = PETSC_TRUE;
2450     mat->assembled     = PETSC_FALSE;
2451   }
2452   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2453   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2454   else {
2455     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2456     const PetscInt *irowm, *icolm;
2457 
2458     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2459       bufr  = buf;
2460       bufc  = buf + nrow;
2461       irowm = bufr;
2462       icolm = bufc;
2463     } else {
2464       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2465       irowm = bufr;
2466       icolm = bufc;
2467     }
2468     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2469     else irowm = irow;
2470     if (mat->cmap->mapping) {
2471       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2472         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2473       } else icolm = irowm;
2474     } else icolm = icol;
2475     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2476     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2477   }
2478   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2479   PetscFunctionReturn(PETSC_SUCCESS);
2480 }
2481 
2482 /*@
2483   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2484   using a local ordering of the nodes a block at a time.
2485 
2486   Not Collective
2487 
2488   Input Parameters:
2489 + mat  - the matrix
2490 . nrow - number of rows
2491 . irow - the row local indices
2492 . ncol - number of columns
2493 . icol - the column local indices
2494 . y    - a logically two-dimensional array of values
2495 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2496 
2497   Level: intermediate
2498 
2499   Notes:
2500   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2501   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2502 
2503   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2504   options cannot be mixed without intervening calls to the assembly
2505   routines.
2506 
2507   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2508   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2509 
2510   Fortran Notes:
2511   If any of `irow`, `icol`, and `y` are scalars pass them using, for example,
2512 .vb
2513   MatSetValuesBlockedLocal(mat, one, [irow], one, [icol], [y], INSERT_VALUES)
2514 .ve
2515 
2516   If `y` is a two-dimensional array use `reshape()` to pass it as a one dimensional array
2517 
2518   Developer Note:
2519   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2520   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2521 
2522 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2523           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2524 @*/
2525 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2526 {
2527   PetscFunctionBeginHot;
2528   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2529   PetscValidType(mat, 1);
2530   MatCheckPreallocated(mat, 1);
2531   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2532   PetscAssertPointer(irow, 3);
2533   PetscAssertPointer(icol, 5);
2534   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2535   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2536   if (PetscDefined(USE_DEBUG)) {
2537     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2538     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);
2539   }
2540 
2541   if (mat->assembled) {
2542     mat->was_assembled = PETSC_TRUE;
2543     mat->assembled     = PETSC_FALSE;
2544   }
2545   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2546     PetscInt irbs, rbs;
2547     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2548     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2549     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2550   }
2551   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2552     PetscInt icbs, cbs;
2553     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2554     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2555     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2556   }
2557   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2558   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2559   else {
2560     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2561     const PetscInt *irowm, *icolm;
2562 
2563     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2564       bufr  = buf;
2565       bufc  = buf + nrow;
2566       irowm = bufr;
2567       icolm = bufc;
2568     } else {
2569       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2570       irowm = bufr;
2571       icolm = bufc;
2572     }
2573     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2574     else irowm = irow;
2575     if (mat->cmap->mapping) {
2576       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2577         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2578       } else icolm = irowm;
2579     } else icolm = icol;
2580     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2581     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2582   }
2583   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2584   PetscFunctionReturn(PETSC_SUCCESS);
2585 }
2586 
2587 /*@
2588   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2589 
2590   Collective
2591 
2592   Input Parameters:
2593 + mat - the matrix
2594 - x   - the vector to be multiplied
2595 
2596   Output Parameter:
2597 . y - the result
2598 
2599   Level: developer
2600 
2601   Note:
2602   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2603   call `MatMultDiagonalBlock`(A,y,y).
2604 
2605 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2606 @*/
2607 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2608 {
2609   PetscFunctionBegin;
2610   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2611   PetscValidType(mat, 1);
2612   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2613   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2614 
2615   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2616   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2617   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2618   MatCheckPreallocated(mat, 1);
2619 
2620   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2621   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2622   PetscFunctionReturn(PETSC_SUCCESS);
2623 }
2624 
2625 /*@
2626   MatMult - Computes the matrix-vector product, $y = Ax$.
2627 
2628   Neighbor-wise Collective
2629 
2630   Input Parameters:
2631 + mat - the matrix
2632 - x   - the vector to be multiplied
2633 
2634   Output Parameter:
2635 . y - the result
2636 
2637   Level: beginner
2638 
2639   Note:
2640   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2641   call `MatMult`(A,y,y).
2642 
2643 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2644 @*/
2645 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2646 {
2647   PetscFunctionBegin;
2648   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2649   PetscValidType(mat, 1);
2650   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2651   VecCheckAssembled(x);
2652   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2653   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2654   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2655   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2656   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);
2657   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);
2658   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);
2659   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);
2660   PetscCall(VecSetErrorIfLocked(y, 3));
2661   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2662   MatCheckPreallocated(mat, 1);
2663 
2664   PetscCall(VecLockReadPush(x));
2665   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2666   PetscUseTypeMethod(mat, mult, x, y);
2667   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2668   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2669   PetscCall(VecLockReadPop(x));
2670   PetscFunctionReturn(PETSC_SUCCESS);
2671 }
2672 
2673 /*@
2674   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2675 
2676   Neighbor-wise Collective
2677 
2678   Input Parameters:
2679 + mat - the matrix
2680 - x   - the vector to be multiplied
2681 
2682   Output Parameter:
2683 . y - the result
2684 
2685   Level: beginner
2686 
2687   Notes:
2688   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2689   call `MatMultTranspose`(A,y,y).
2690 
2691   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2692   use `MatMultHermitianTranspose()`
2693 
2694 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2695 @*/
2696 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2697 {
2698   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2699 
2700   PetscFunctionBegin;
2701   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2702   PetscValidType(mat, 1);
2703   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2704   VecCheckAssembled(x);
2705   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2706 
2707   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2708   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2709   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2710   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);
2711   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);
2712   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);
2713   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);
2714   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2715   MatCheckPreallocated(mat, 1);
2716 
2717   if (!mat->ops->multtranspose) {
2718     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2719     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);
2720   } else op = mat->ops->multtranspose;
2721   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2722   PetscCall(VecLockReadPush(x));
2723   PetscCall((*op)(mat, x, y));
2724   PetscCall(VecLockReadPop(x));
2725   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2726   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2727   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2728   PetscFunctionReturn(PETSC_SUCCESS);
2729 }
2730 
2731 /*@
2732   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * x$.
2733 
2734   Neighbor-wise Collective
2735 
2736   Input Parameters:
2737 + mat - the matrix
2738 - x   - the vector to be multiplied
2739 
2740   Output Parameter:
2741 . y - the result
2742 
2743   Level: beginner
2744 
2745   Notes:
2746   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2747   call `MatMultHermitianTranspose`(A,y,y).
2748 
2749   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2750 
2751   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2752 
2753 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2754 @*/
2755 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2756 {
2757   PetscFunctionBegin;
2758   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2759   PetscValidType(mat, 1);
2760   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2761   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2762 
2763   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2764   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2765   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2766   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);
2767   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);
2768   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);
2769   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);
2770   MatCheckPreallocated(mat, 1);
2771 
2772   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2773 #if defined(PETSC_USE_COMPLEX)
2774   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2775     PetscCall(VecLockReadPush(x));
2776     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2777     else PetscUseTypeMethod(mat, mult, x, y);
2778     PetscCall(VecLockReadPop(x));
2779   } else {
2780     Vec w;
2781     PetscCall(VecDuplicate(x, &w));
2782     PetscCall(VecCopy(x, w));
2783     PetscCall(VecConjugate(w));
2784     PetscCall(MatMultTranspose(mat, w, y));
2785     PetscCall(VecDestroy(&w));
2786     PetscCall(VecConjugate(y));
2787   }
2788   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2789 #else
2790   PetscCall(MatMultTranspose(mat, x, y));
2791 #endif
2792   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2793   PetscFunctionReturn(PETSC_SUCCESS);
2794 }
2795 
2796 /*@
2797   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2798 
2799   Neighbor-wise Collective
2800 
2801   Input Parameters:
2802 + mat - the matrix
2803 . v1  - the vector to be multiplied by `mat`
2804 - v2  - the vector to be added to the result
2805 
2806   Output Parameter:
2807 . v3 - the result
2808 
2809   Level: beginner
2810 
2811   Note:
2812   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2813   call `MatMultAdd`(A,v1,v2,v1).
2814 
2815 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2816 @*/
2817 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2818 {
2819   PetscFunctionBegin;
2820   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2821   PetscValidType(mat, 1);
2822   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2823   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2824   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2825 
2826   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2827   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2828   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);
2829   /* 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);
2830      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); */
2831   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);
2832   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);
2833   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2834   MatCheckPreallocated(mat, 1);
2835 
2836   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2837   PetscCall(VecLockReadPush(v1));
2838   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2839   PetscCall(VecLockReadPop(v1));
2840   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2841   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2842   PetscFunctionReturn(PETSC_SUCCESS);
2843 }
2844 
2845 /*@
2846   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2847 
2848   Neighbor-wise Collective
2849 
2850   Input Parameters:
2851 + mat - the matrix
2852 . v1  - the vector to be multiplied by the transpose of the matrix
2853 - v2  - the vector to be added to the result
2854 
2855   Output Parameter:
2856 . v3 - the result
2857 
2858   Level: beginner
2859 
2860   Note:
2861   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2862   call `MatMultTransposeAdd`(A,v1,v2,v1).
2863 
2864 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2865 @*/
2866 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2867 {
2868   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2869 
2870   PetscFunctionBegin;
2871   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2872   PetscValidType(mat, 1);
2873   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2874   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2875   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2876 
2877   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2878   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2879   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);
2880   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);
2881   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);
2882   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2883   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2884   MatCheckPreallocated(mat, 1);
2885 
2886   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2887   PetscCall(VecLockReadPush(v1));
2888   PetscCall((*op)(mat, v1, v2, v3));
2889   PetscCall(VecLockReadPop(v1));
2890   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2891   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2892   PetscFunctionReturn(PETSC_SUCCESS);
2893 }
2894 
2895 /*@
2896   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2897 
2898   Neighbor-wise Collective
2899 
2900   Input Parameters:
2901 + mat - the matrix
2902 . v1  - the vector to be multiplied by the Hermitian transpose
2903 - v2  - the vector to be added to the result
2904 
2905   Output Parameter:
2906 . v3 - the result
2907 
2908   Level: beginner
2909 
2910   Note:
2911   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2912   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2913 
2914 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2915 @*/
2916 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2917 {
2918   PetscFunctionBegin;
2919   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2920   PetscValidType(mat, 1);
2921   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2922   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2923   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2924 
2925   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2926   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2927   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2928   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);
2929   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);
2930   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);
2931   MatCheckPreallocated(mat, 1);
2932 
2933   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2934   PetscCall(VecLockReadPush(v1));
2935   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2936   else {
2937     Vec w, z;
2938     PetscCall(VecDuplicate(v1, &w));
2939     PetscCall(VecCopy(v1, w));
2940     PetscCall(VecConjugate(w));
2941     PetscCall(VecDuplicate(v3, &z));
2942     PetscCall(MatMultTranspose(mat, w, z));
2943     PetscCall(VecDestroy(&w));
2944     PetscCall(VecConjugate(z));
2945     if (v2 != v3) {
2946       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2947     } else {
2948       PetscCall(VecAXPY(v3, 1.0, z));
2949     }
2950     PetscCall(VecDestroy(&z));
2951   }
2952   PetscCall(VecLockReadPop(v1));
2953   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2954   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2955   PetscFunctionReturn(PETSC_SUCCESS);
2956 }
2957 
2958 /*@
2959   MatGetFactorType - gets the type of factorization a matrix is
2960 
2961   Not Collective
2962 
2963   Input Parameter:
2964 . mat - the matrix
2965 
2966   Output Parameter:
2967 . 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`
2968 
2969   Level: intermediate
2970 
2971 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2972           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2973 @*/
2974 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2975 {
2976   PetscFunctionBegin;
2977   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2978   PetscValidType(mat, 1);
2979   PetscAssertPointer(t, 2);
2980   *t = mat->factortype;
2981   PetscFunctionReturn(PETSC_SUCCESS);
2982 }
2983 
2984 /*@
2985   MatSetFactorType - sets the type of factorization a matrix is
2986 
2987   Logically Collective
2988 
2989   Input Parameters:
2990 + mat - the matrix
2991 - 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`
2992 
2993   Level: intermediate
2994 
2995 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2996           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2997 @*/
2998 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2999 {
3000   PetscFunctionBegin;
3001   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3002   PetscValidType(mat, 1);
3003   mat->factortype = t;
3004   PetscFunctionReturn(PETSC_SUCCESS);
3005 }
3006 
3007 /*@
3008   MatGetInfo - Returns information about matrix storage (number of
3009   nonzeros, memory, etc.).
3010 
3011   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
3012 
3013   Input Parameters:
3014 + mat  - the matrix
3015 - 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)
3016 
3017   Output Parameter:
3018 . info - matrix information context
3019 
3020   Options Database Key:
3021 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
3022 
3023   Level: intermediate
3024 
3025   Notes:
3026   The `MatInfo` context contains a variety of matrix data, including
3027   number of nonzeros allocated and used, number of mallocs during
3028   matrix assembly, etc.  Additional information for factored matrices
3029   is provided (such as the fill ratio, number of mallocs during
3030   factorization, etc.).
3031 
3032   Example:
3033   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
3034   data within the `MatInfo` context.  For example,
3035 .vb
3036       MatInfo info;
3037       Mat     A;
3038       double  mal, nz_a, nz_u;
3039 
3040       MatGetInfo(A, MAT_LOCAL, &info);
3041       mal  = info.mallocs;
3042       nz_a = info.nz_allocated;
3043 .ve
3044 
3045   Fortran Note:
3046   Declare info as a `MatInfo` array of dimension `MAT_INFO_SIZE`, and then extract the parameters
3047   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
3048   a complete list of parameter names.
3049 .vb
3050       MatInfo info(MAT_INFO_SIZE)
3051       double  precision mal, nz_a
3052       Mat     A
3053       integer ierr
3054 
3055       call MatGetInfo(A, MAT_LOCAL, info, ierr)
3056       mal = info(MAT_INFO_MALLOCS)
3057       nz_a = info(MAT_INFO_NZ_ALLOCATED)
3058 .ve
3059 
3060 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3061 @*/
3062 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3063 {
3064   PetscFunctionBegin;
3065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3066   PetscValidType(mat, 1);
3067   PetscAssertPointer(info, 3);
3068   MatCheckPreallocated(mat, 1);
3069   PetscUseTypeMethod(mat, getinfo, flag, info);
3070   PetscFunctionReturn(PETSC_SUCCESS);
3071 }
3072 
3073 /*
3074    This is used by external packages where it is not easy to get the info from the actual
3075    matrix factorization.
3076 */
3077 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3078 {
3079   PetscFunctionBegin;
3080   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3081   PetscFunctionReturn(PETSC_SUCCESS);
3082 }
3083 
3084 /*@
3085   MatLUFactor - Performs in-place LU factorization of matrix.
3086 
3087   Collective
3088 
3089   Input Parameters:
3090 + mat  - the matrix
3091 . row  - row permutation
3092 . col  - column permutation
3093 - info - options for factorization, includes
3094 .vb
3095           fill - expected fill as ratio of original fill.
3096           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3097                    Run with the option -info to determine an optimal value to use
3098 .ve
3099 
3100   Level: developer
3101 
3102   Notes:
3103   Most users should employ the `KSP` interface for linear solvers
3104   instead of working directly with matrix algebra routines such as this.
3105   See, e.g., `KSPCreate()`.
3106 
3107   This changes the state of the matrix to a factored matrix; it cannot be used
3108   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3109 
3110   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3111   when not using `KSP`.
3112 
3113   Developer Note:
3114   The Fortran interface is not autogenerated as the
3115   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3116 
3117 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3118           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3119 @*/
3120 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3121 {
3122   MatFactorInfo tinfo;
3123 
3124   PetscFunctionBegin;
3125   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3126   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3127   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3128   if (info) PetscAssertPointer(info, 4);
3129   PetscValidType(mat, 1);
3130   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3131   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3132   MatCheckPreallocated(mat, 1);
3133   if (!info) {
3134     PetscCall(MatFactorInfoInitialize(&tinfo));
3135     info = &tinfo;
3136   }
3137 
3138   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3139   PetscUseTypeMethod(mat, lufactor, row, col, info);
3140   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3141   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3142   PetscFunctionReturn(PETSC_SUCCESS);
3143 }
3144 
3145 /*@
3146   MatILUFactor - Performs in-place ILU factorization of matrix.
3147 
3148   Collective
3149 
3150   Input Parameters:
3151 + mat  - the matrix
3152 . row  - row permutation
3153 . col  - column permutation
3154 - info - structure containing
3155 .vb
3156       levels - number of levels of fill.
3157       expected fill - as ratio of original fill.
3158       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3159                 missing diagonal entries)
3160 .ve
3161 
3162   Level: developer
3163 
3164   Notes:
3165   Most users should employ the `KSP` interface for linear solvers
3166   instead of working directly with matrix algebra routines such as this.
3167   See, e.g., `KSPCreate()`.
3168 
3169   Probably really in-place only when level of fill is zero, otherwise allocates
3170   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3171   when not using `KSP`.
3172 
3173   Developer Note:
3174   The Fortran interface is not autogenerated as the
3175   interface definition cannot be generated correctly [due to MatFactorInfo]
3176 
3177 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3178 @*/
3179 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3180 {
3181   PetscFunctionBegin;
3182   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3183   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3184   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3185   PetscAssertPointer(info, 4);
3186   PetscValidType(mat, 1);
3187   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3188   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3189   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3190   MatCheckPreallocated(mat, 1);
3191 
3192   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3193   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3194   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3195   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3196   PetscFunctionReturn(PETSC_SUCCESS);
3197 }
3198 
3199 /*@
3200   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3201   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3202 
3203   Collective
3204 
3205   Input Parameters:
3206 + fact - the factor matrix obtained with `MatGetFactor()`
3207 . mat  - the matrix
3208 . row  - the row permutation
3209 . col  - the column permutation
3210 - info - options for factorization, includes
3211 .vb
3212           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3213           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3214 .ve
3215 
3216   Level: developer
3217 
3218   Notes:
3219   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3220 
3221   Most users should employ the simplified `KSP` interface for linear solvers
3222   instead of working directly with matrix algebra routines such as this.
3223   See, e.g., `KSPCreate()`.
3224 
3225   Developer Note:
3226   The Fortran interface is not autogenerated as the
3227   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3228 
3229 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3230 @*/
3231 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3232 {
3233   MatFactorInfo tinfo;
3234 
3235   PetscFunctionBegin;
3236   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3238   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3239   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3240   if (info) PetscAssertPointer(info, 5);
3241   PetscValidType(fact, 1);
3242   PetscValidType(mat, 2);
3243   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3244   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3245   MatCheckPreallocated(mat, 2);
3246   if (!info) {
3247     PetscCall(MatFactorInfoInitialize(&tinfo));
3248     info = &tinfo;
3249   }
3250 
3251   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3252   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3253   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3254   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3255   PetscFunctionReturn(PETSC_SUCCESS);
3256 }
3257 
3258 /*@
3259   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3260   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3261 
3262   Collective
3263 
3264   Input Parameters:
3265 + fact - the factor matrix obtained with `MatGetFactor()`
3266 . mat  - the matrix
3267 - info - options for factorization
3268 
3269   Level: developer
3270 
3271   Notes:
3272   See `MatLUFactor()` for in-place factorization.  See
3273   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3274 
3275   Most users should employ the `KSP` interface for linear solvers
3276   instead of working directly with matrix algebra routines such as this.
3277   See, e.g., `KSPCreate()`.
3278 
3279   Developer Note:
3280   The Fortran interface is not autogenerated as the
3281   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3282 
3283 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3284 @*/
3285 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3286 {
3287   MatFactorInfo tinfo;
3288 
3289   PetscFunctionBegin;
3290   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3291   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3292   PetscValidType(fact, 1);
3293   PetscValidType(mat, 2);
3294   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3295   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,
3296              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3297 
3298   MatCheckPreallocated(mat, 2);
3299   if (!info) {
3300     PetscCall(MatFactorInfoInitialize(&tinfo));
3301     info = &tinfo;
3302   }
3303 
3304   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3305   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3306   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3307   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3308   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3309   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3310   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3311   PetscFunctionReturn(PETSC_SUCCESS);
3312 }
3313 
3314 /*@
3315   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3316   symmetric matrix.
3317 
3318   Collective
3319 
3320   Input Parameters:
3321 + mat  - the matrix
3322 . perm - row and column permutations
3323 - info - expected fill as ratio of original fill
3324 
3325   Level: developer
3326 
3327   Notes:
3328   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3329   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3330 
3331   Most users should employ the `KSP` interface for linear solvers
3332   instead of working directly with matrix algebra routines such as this.
3333   See, e.g., `KSPCreate()`.
3334 
3335   Developer Note:
3336   The Fortran interface is not autogenerated as the
3337   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3338 
3339 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3340           `MatGetOrdering()`
3341 @*/
3342 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3343 {
3344   MatFactorInfo tinfo;
3345 
3346   PetscFunctionBegin;
3347   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3348   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3349   if (info) PetscAssertPointer(info, 3);
3350   PetscValidType(mat, 1);
3351   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3352   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3353   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3354   MatCheckPreallocated(mat, 1);
3355   if (!info) {
3356     PetscCall(MatFactorInfoInitialize(&tinfo));
3357     info = &tinfo;
3358   }
3359 
3360   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3361   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3362   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3363   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3364   PetscFunctionReturn(PETSC_SUCCESS);
3365 }
3366 
3367 /*@
3368   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3369   of a symmetric matrix.
3370 
3371   Collective
3372 
3373   Input Parameters:
3374 + fact - the factor matrix obtained with `MatGetFactor()`
3375 . mat  - the matrix
3376 . perm - row and column permutations
3377 - info - options for factorization, includes
3378 .vb
3379           fill - expected fill as ratio of original fill.
3380           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3381                    Run with the option -info to determine an optimal value to use
3382 .ve
3383 
3384   Level: developer
3385 
3386   Notes:
3387   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3388   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3389 
3390   Most users should employ the `KSP` interface for linear solvers
3391   instead of working directly with matrix algebra routines such as this.
3392   See, e.g., `KSPCreate()`.
3393 
3394   Developer Note:
3395   The Fortran interface is not autogenerated as the
3396   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3397 
3398 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3399           `MatGetOrdering()`
3400 @*/
3401 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3402 {
3403   MatFactorInfo tinfo;
3404 
3405   PetscFunctionBegin;
3406   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3407   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3408   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3409   if (info) PetscAssertPointer(info, 4);
3410   PetscValidType(fact, 1);
3411   PetscValidType(mat, 2);
3412   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3413   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3414   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3415   MatCheckPreallocated(mat, 2);
3416   if (!info) {
3417     PetscCall(MatFactorInfoInitialize(&tinfo));
3418     info = &tinfo;
3419   }
3420 
3421   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3422   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3423   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3424   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3425   PetscFunctionReturn(PETSC_SUCCESS);
3426 }
3427 
3428 /*@
3429   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3430   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3431   `MatCholeskyFactorSymbolic()`.
3432 
3433   Collective
3434 
3435   Input Parameters:
3436 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3437 . mat  - the initial matrix that is to be factored
3438 - info - options for factorization
3439 
3440   Level: developer
3441 
3442   Note:
3443   Most users should employ the `KSP` interface for linear solvers
3444   instead of working directly with matrix algebra routines such as this.
3445   See, e.g., `KSPCreate()`.
3446 
3447   Developer Note:
3448   The Fortran interface is not autogenerated as the
3449   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3450 
3451 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3452 @*/
3453 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3454 {
3455   MatFactorInfo tinfo;
3456 
3457   PetscFunctionBegin;
3458   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3460   PetscValidType(fact, 1);
3461   PetscValidType(mat, 2);
3462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3463   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,
3464              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3465   MatCheckPreallocated(mat, 2);
3466   if (!info) {
3467     PetscCall(MatFactorInfoInitialize(&tinfo));
3468     info = &tinfo;
3469   }
3470 
3471   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3472   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3473   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3474   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3475   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3476   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3477   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3478   PetscFunctionReturn(PETSC_SUCCESS);
3479 }
3480 
3481 /*@
3482   MatQRFactor - Performs in-place QR factorization of matrix.
3483 
3484   Collective
3485 
3486   Input Parameters:
3487 + mat  - the matrix
3488 . col  - column permutation
3489 - info - options for factorization, includes
3490 .vb
3491           fill - expected fill as ratio of original fill.
3492           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3493                    Run with the option -info to determine an optimal value to use
3494 .ve
3495 
3496   Level: developer
3497 
3498   Notes:
3499   Most users should employ the `KSP` interface for linear solvers
3500   instead of working directly with matrix algebra routines such as this.
3501   See, e.g., `KSPCreate()`.
3502 
3503   This changes the state of the matrix to a factored matrix; it cannot be used
3504   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3505 
3506   Developer Note:
3507   The Fortran interface is not autogenerated as the
3508   interface definition cannot be generated correctly [due to MatFactorInfo]
3509 
3510 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3511           `MatSetUnfactored()`
3512 @*/
3513 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3514 {
3515   PetscFunctionBegin;
3516   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3517   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3518   if (info) PetscAssertPointer(info, 3);
3519   PetscValidType(mat, 1);
3520   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3521   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3522   MatCheckPreallocated(mat, 1);
3523   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3524   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3525   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3526   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3527   PetscFunctionReturn(PETSC_SUCCESS);
3528 }
3529 
3530 /*@
3531   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3532   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3533 
3534   Collective
3535 
3536   Input Parameters:
3537 + fact - the factor matrix obtained with `MatGetFactor()`
3538 . mat  - the matrix
3539 . col  - column permutation
3540 - info - options for factorization, includes
3541 .vb
3542           fill - expected fill as ratio of original fill.
3543           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3544                    Run with the option -info to determine an optimal value to use
3545 .ve
3546 
3547   Level: developer
3548 
3549   Note:
3550   Most users should employ the `KSP` interface for linear solvers
3551   instead of working directly with matrix algebra routines such as this.
3552   See, e.g., `KSPCreate()`.
3553 
3554   Developer Note:
3555   The Fortran interface is not autogenerated as the
3556   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3557 
3558 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3559 @*/
3560 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3561 {
3562   MatFactorInfo tinfo;
3563 
3564   PetscFunctionBegin;
3565   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3567   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3568   if (info) PetscAssertPointer(info, 4);
3569   PetscValidType(fact, 1);
3570   PetscValidType(mat, 2);
3571   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3572   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3573   MatCheckPreallocated(mat, 2);
3574   if (!info) {
3575     PetscCall(MatFactorInfoInitialize(&tinfo));
3576     info = &tinfo;
3577   }
3578 
3579   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3580   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3581   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3582   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3583   PetscFunctionReturn(PETSC_SUCCESS);
3584 }
3585 
3586 /*@
3587   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3588   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3589 
3590   Collective
3591 
3592   Input Parameters:
3593 + fact - the factor matrix obtained with `MatGetFactor()`
3594 . mat  - the matrix
3595 - info - options for factorization
3596 
3597   Level: developer
3598 
3599   Notes:
3600   See `MatQRFactor()` for in-place factorization.
3601 
3602   Most users should employ the `KSP` interface for linear solvers
3603   instead of working directly with matrix algebra routines such as this.
3604   See, e.g., `KSPCreate()`.
3605 
3606   Developer Note:
3607   The Fortran interface is not autogenerated as the
3608   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3609 
3610 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3611 @*/
3612 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3613 {
3614   MatFactorInfo tinfo;
3615 
3616   PetscFunctionBegin;
3617   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3618   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3619   PetscValidType(fact, 1);
3620   PetscValidType(mat, 2);
3621   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3622   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,
3623              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3624 
3625   MatCheckPreallocated(mat, 2);
3626   if (!info) {
3627     PetscCall(MatFactorInfoInitialize(&tinfo));
3628     info = &tinfo;
3629   }
3630 
3631   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3632   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3633   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3634   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3635   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3636   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3637   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3638   PetscFunctionReturn(PETSC_SUCCESS);
3639 }
3640 
3641 /*@
3642   MatSolve - Solves $A x = b$, given a factored matrix.
3643 
3644   Neighbor-wise Collective
3645 
3646   Input Parameters:
3647 + mat - the factored matrix
3648 - b   - the right-hand-side vector
3649 
3650   Output Parameter:
3651 . x - the result vector
3652 
3653   Level: developer
3654 
3655   Notes:
3656   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3657   call `MatSolve`(A,x,x).
3658 
3659   Most users should employ the `KSP` interface for linear solvers
3660   instead of working directly with matrix algebra routines such as this.
3661   See, e.g., `KSPCreate()`.
3662 
3663 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3664 @*/
3665 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3666 {
3667   PetscFunctionBegin;
3668   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3669   PetscValidType(mat, 1);
3670   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3671   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3672   PetscCheckSameComm(mat, 1, b, 2);
3673   PetscCheckSameComm(mat, 1, x, 3);
3674   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3675   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);
3676   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);
3677   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);
3678   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3679   MatCheckPreallocated(mat, 1);
3680 
3681   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3682   PetscCall(VecFlag(x, mat->factorerrortype));
3683   if (mat->factorerrortype) {
3684     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3685   } else PetscUseTypeMethod(mat, solve, b, x);
3686   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3687   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3688   PetscFunctionReturn(PETSC_SUCCESS);
3689 }
3690 
3691 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3692 {
3693   Vec      b, x;
3694   PetscInt N, i;
3695   PetscErrorCode (*f)(Mat, Vec, Vec);
3696   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3697 
3698   PetscFunctionBegin;
3699   if (A->factorerrortype) {
3700     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3701     PetscCall(MatSetInf(X));
3702     PetscFunctionReturn(PETSC_SUCCESS);
3703   }
3704   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3705   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3706   PetscCall(MatBoundToCPU(A, &Abound));
3707   if (!Abound) {
3708     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3709     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3710   }
3711 #if PetscDefined(HAVE_CUDA)
3712   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3713   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3714 #elif PetscDefined(HAVE_HIP)
3715   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3716   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3717 #endif
3718   PetscCall(MatGetSize(B, NULL, &N));
3719   for (i = 0; i < N; i++) {
3720     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3721     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3722     PetscCall((*f)(A, b, x));
3723     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3724     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3725   }
3726   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3727   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3728   PetscFunctionReturn(PETSC_SUCCESS);
3729 }
3730 
3731 /*@
3732   MatMatSolve - Solves $A X = B$, given a factored matrix.
3733 
3734   Neighbor-wise Collective
3735 
3736   Input Parameters:
3737 + A - the factored matrix
3738 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3739 
3740   Output Parameter:
3741 . X - the result matrix (dense matrix)
3742 
3743   Level: developer
3744 
3745   Note:
3746   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3747   otherwise, `B` and `X` cannot be the same.
3748 
3749 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3750 @*/
3751 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3752 {
3753   PetscFunctionBegin;
3754   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3755   PetscValidType(A, 1);
3756   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3757   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3758   PetscCheckSameComm(A, 1, B, 2);
3759   PetscCheckSameComm(A, 1, X, 3);
3760   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);
3761   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);
3762   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");
3763   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3764   MatCheckPreallocated(A, 1);
3765 
3766   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3767   if (!A->ops->matsolve) {
3768     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3769     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3770   } else PetscUseTypeMethod(A, matsolve, B, X);
3771   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3772   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3773   PetscFunctionReturn(PETSC_SUCCESS);
3774 }
3775 
3776 /*@
3777   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3778 
3779   Neighbor-wise Collective
3780 
3781   Input Parameters:
3782 + A - the factored matrix
3783 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3784 
3785   Output Parameter:
3786 . X - the result matrix (dense matrix)
3787 
3788   Level: developer
3789 
3790   Note:
3791   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3792   call `MatMatSolveTranspose`(A,X,X).
3793 
3794 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3795 @*/
3796 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3797 {
3798   PetscFunctionBegin;
3799   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3800   PetscValidType(A, 1);
3801   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3802   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3803   PetscCheckSameComm(A, 1, B, 2);
3804   PetscCheckSameComm(A, 1, X, 3);
3805   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3806   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);
3807   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);
3808   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);
3809   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");
3810   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3811   MatCheckPreallocated(A, 1);
3812 
3813   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3814   if (!A->ops->matsolvetranspose) {
3815     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3816     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3817   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3818   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3819   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3820   PetscFunctionReturn(PETSC_SUCCESS);
3821 }
3822 
3823 /*@
3824   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3825 
3826   Neighbor-wise Collective
3827 
3828   Input Parameters:
3829 + A  - the factored matrix
3830 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3831 
3832   Output Parameter:
3833 . X - the result matrix (dense matrix)
3834 
3835   Level: developer
3836 
3837   Note:
3838   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
3839   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3840 
3841 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3842 @*/
3843 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3844 {
3845   PetscFunctionBegin;
3846   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3847   PetscValidType(A, 1);
3848   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3849   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3850   PetscCheckSameComm(A, 1, Bt, 2);
3851   PetscCheckSameComm(A, 1, X, 3);
3852 
3853   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3854   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);
3855   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);
3856   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");
3857   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3858   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3859   MatCheckPreallocated(A, 1);
3860 
3861   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3862   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3863   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3864   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3865   PetscFunctionReturn(PETSC_SUCCESS);
3866 }
3867 
3868 /*@
3869   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3870   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3871 
3872   Neighbor-wise Collective
3873 
3874   Input Parameters:
3875 + mat - the factored matrix
3876 - b   - the right-hand-side vector
3877 
3878   Output Parameter:
3879 . x - the result vector
3880 
3881   Level: developer
3882 
3883   Notes:
3884   `MatSolve()` should be used for most applications, as it performs
3885   a forward solve followed by a backward solve.
3886 
3887   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3888   call `MatForwardSolve`(A,x,x).
3889 
3890   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3891   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3892   `MatForwardSolve()` solves $U^T*D y = b$, and
3893   `MatBackwardSolve()` solves $U x = y$.
3894   Thus they do not provide a symmetric preconditioner.
3895 
3896 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3897 @*/
3898 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3899 {
3900   PetscFunctionBegin;
3901   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3902   PetscValidType(mat, 1);
3903   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3904   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3905   PetscCheckSameComm(mat, 1, b, 2);
3906   PetscCheckSameComm(mat, 1, x, 3);
3907   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3908   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);
3909   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);
3910   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);
3911   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3912   MatCheckPreallocated(mat, 1);
3913 
3914   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3915   PetscUseTypeMethod(mat, forwardsolve, b, x);
3916   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3917   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3918   PetscFunctionReturn(PETSC_SUCCESS);
3919 }
3920 
3921 /*@
3922   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3923   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3924 
3925   Neighbor-wise Collective
3926 
3927   Input Parameters:
3928 + mat - the factored matrix
3929 - b   - the right-hand-side vector
3930 
3931   Output Parameter:
3932 . x - the result vector
3933 
3934   Level: developer
3935 
3936   Notes:
3937   `MatSolve()` should be used for most applications, as it performs
3938   a forward solve followed by a backward solve.
3939 
3940   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3941   call `MatBackwardSolve`(A,x,x).
3942 
3943   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3944   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3945   `MatForwardSolve()` solves $U^T*D y = b$, and
3946   `MatBackwardSolve()` solves $U x = y$.
3947   Thus they do not provide a symmetric preconditioner.
3948 
3949 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3950 @*/
3951 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3952 {
3953   PetscFunctionBegin;
3954   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3955   PetscValidType(mat, 1);
3956   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3957   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3958   PetscCheckSameComm(mat, 1, b, 2);
3959   PetscCheckSameComm(mat, 1, x, 3);
3960   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3961   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);
3962   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);
3963   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);
3964   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3965   MatCheckPreallocated(mat, 1);
3966 
3967   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3968   PetscUseTypeMethod(mat, backwardsolve, b, x);
3969   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3970   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3971   PetscFunctionReturn(PETSC_SUCCESS);
3972 }
3973 
3974 /*@
3975   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3976 
3977   Neighbor-wise Collective
3978 
3979   Input Parameters:
3980 + mat - the factored matrix
3981 . b   - the right-hand-side vector
3982 - y   - the vector to be added to
3983 
3984   Output Parameter:
3985 . x - the result vector
3986 
3987   Level: developer
3988 
3989   Note:
3990   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3991   call `MatSolveAdd`(A,x,y,x).
3992 
3993 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3994 @*/
3995 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3996 {
3997   PetscScalar one = 1.0;
3998   Vec         tmp;
3999 
4000   PetscFunctionBegin;
4001   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4002   PetscValidType(mat, 1);
4003   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4004   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4005   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4006   PetscCheckSameComm(mat, 1, b, 2);
4007   PetscCheckSameComm(mat, 1, y, 3);
4008   PetscCheckSameComm(mat, 1, x, 4);
4009   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4010   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);
4011   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);
4012   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);
4013   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);
4014   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);
4015   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4016   MatCheckPreallocated(mat, 1);
4017 
4018   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
4019   PetscCall(VecFlag(x, mat->factorerrortype));
4020   if (mat->factorerrortype) {
4021     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4022   } else if (mat->ops->solveadd) {
4023     PetscUseTypeMethod(mat, solveadd, b, y, x);
4024   } else {
4025     /* do the solve then the add manually */
4026     if (x != y) {
4027       PetscCall(MatSolve(mat, b, x));
4028       PetscCall(VecAXPY(x, one, y));
4029     } else {
4030       PetscCall(VecDuplicate(x, &tmp));
4031       PetscCall(VecCopy(x, tmp));
4032       PetscCall(MatSolve(mat, b, x));
4033       PetscCall(VecAXPY(x, one, tmp));
4034       PetscCall(VecDestroy(&tmp));
4035     }
4036   }
4037   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
4038   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4039   PetscFunctionReturn(PETSC_SUCCESS);
4040 }
4041 
4042 /*@
4043   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
4044 
4045   Neighbor-wise Collective
4046 
4047   Input Parameters:
4048 + mat - the factored matrix
4049 - b   - the right-hand-side vector
4050 
4051   Output Parameter:
4052 . x - the result vector
4053 
4054   Level: developer
4055 
4056   Notes:
4057   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4058   call `MatSolveTranspose`(A,x,x).
4059 
4060   Most users should employ the `KSP` interface for linear solvers
4061   instead of working directly with matrix algebra routines such as this.
4062   See, e.g., `KSPCreate()`.
4063 
4064 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4065 @*/
4066 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4067 {
4068   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4069 
4070   PetscFunctionBegin;
4071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4072   PetscValidType(mat, 1);
4073   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4074   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4075   PetscCheckSameComm(mat, 1, b, 2);
4076   PetscCheckSameComm(mat, 1, x, 3);
4077   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4078   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);
4079   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);
4080   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4081   MatCheckPreallocated(mat, 1);
4082   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4083   PetscCall(VecFlag(x, mat->factorerrortype));
4084   if (mat->factorerrortype) {
4085     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4086   } else {
4087     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4088     PetscCall((*f)(mat, b, x));
4089   }
4090   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4091   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4092   PetscFunctionReturn(PETSC_SUCCESS);
4093 }
4094 
4095 /*@
4096   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4097   factored matrix.
4098 
4099   Neighbor-wise Collective
4100 
4101   Input Parameters:
4102 + mat - the factored matrix
4103 . b   - the right-hand-side vector
4104 - y   - the vector to be added to
4105 
4106   Output Parameter:
4107 . x - the result vector
4108 
4109   Level: developer
4110 
4111   Note:
4112   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4113   call `MatSolveTransposeAdd`(A,x,y,x).
4114 
4115 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4116 @*/
4117 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4118 {
4119   PetscScalar one = 1.0;
4120   Vec         tmp;
4121   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4122 
4123   PetscFunctionBegin;
4124   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4125   PetscValidType(mat, 1);
4126   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4127   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4128   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4129   PetscCheckSameComm(mat, 1, b, 2);
4130   PetscCheckSameComm(mat, 1, y, 3);
4131   PetscCheckSameComm(mat, 1, x, 4);
4132   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4133   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);
4134   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);
4135   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);
4136   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);
4137   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4138   MatCheckPreallocated(mat, 1);
4139 
4140   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4141   PetscCall(VecFlag(x, mat->factorerrortype));
4142   if (mat->factorerrortype) {
4143     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4144   } else if (f) {
4145     PetscCall((*f)(mat, b, y, x));
4146   } else {
4147     /* do the solve then the add manually */
4148     if (x != y) {
4149       PetscCall(MatSolveTranspose(mat, b, x));
4150       PetscCall(VecAXPY(x, one, y));
4151     } else {
4152       PetscCall(VecDuplicate(x, &tmp));
4153       PetscCall(VecCopy(x, tmp));
4154       PetscCall(MatSolveTranspose(mat, b, x));
4155       PetscCall(VecAXPY(x, one, tmp));
4156       PetscCall(VecDestroy(&tmp));
4157     }
4158   }
4159   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4160   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4161   PetscFunctionReturn(PETSC_SUCCESS);
4162 }
4163 
4164 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4165 /*@
4166   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4167 
4168   Neighbor-wise Collective
4169 
4170   Input Parameters:
4171 + mat   - the matrix
4172 . b     - the right-hand side
4173 . omega - the relaxation factor
4174 . flag  - flag indicating the type of SOR (see below)
4175 . shift - diagonal shift
4176 . its   - the number of iterations
4177 - lits  - the number of local iterations
4178 
4179   Output Parameter:
4180 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4181 
4182   SOR Flags:
4183 +     `SOR_FORWARD_SWEEP` - forward SOR
4184 .     `SOR_BACKWARD_SWEEP` - backward SOR
4185 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4186 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4187 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4188 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4189 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4190 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4191   upper/lower triangular part of matrix to
4192   vector (with omega)
4193 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4194 
4195   Level: developer
4196 
4197   Notes:
4198   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4199   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4200   on each processor.
4201 
4202   Application programmers will not generally use `MatSOR()` directly,
4203   but instead will employ the `KSP`/`PC` interface.
4204 
4205   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4206 
4207   Most users should employ the `KSP` interface for linear solvers
4208   instead of working directly with matrix algebra routines such as this.
4209   See, e.g., `KSPCreate()`.
4210 
4211   Vectors `x` and `b` CANNOT be the same
4212 
4213   The flags are implemented as bitwise inclusive or operations.
4214   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4215   to specify a zero initial guess for SSOR.
4216 
4217   Developer Note:
4218   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4219 
4220 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4221 @*/
4222 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4223 {
4224   PetscFunctionBegin;
4225   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4226   PetscValidType(mat, 1);
4227   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4228   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4229   PetscCheckSameComm(mat, 1, b, 2);
4230   PetscCheckSameComm(mat, 1, x, 8);
4231   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4232   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4233   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);
4234   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);
4235   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);
4236   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4237   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4238   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4239 
4240   MatCheckPreallocated(mat, 1);
4241   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4242   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4243   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4244   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4245   PetscFunctionReturn(PETSC_SUCCESS);
4246 }
4247 
4248 /*
4249       Default matrix copy routine.
4250 */
4251 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4252 {
4253   PetscInt           i, rstart = 0, rend = 0, nz;
4254   const PetscInt    *cwork;
4255   const PetscScalar *vwork;
4256 
4257   PetscFunctionBegin;
4258   if (B->assembled) PetscCall(MatZeroEntries(B));
4259   if (str == SAME_NONZERO_PATTERN) {
4260     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4261     for (i = rstart; i < rend; i++) {
4262       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4263       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4264       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4265     }
4266   } else {
4267     PetscCall(MatAYPX(B, 0.0, A, str));
4268   }
4269   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4270   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4271   PetscFunctionReturn(PETSC_SUCCESS);
4272 }
4273 
4274 /*@
4275   MatCopy - Copies a matrix to another matrix.
4276 
4277   Collective
4278 
4279   Input Parameters:
4280 + A   - the matrix
4281 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4282 
4283   Output Parameter:
4284 . B - where the copy is put
4285 
4286   Level: intermediate
4287 
4288   Notes:
4289   If you use `SAME_NONZERO_PATTERN`, then the two matrices must have the same nonzero pattern or the routine will crash.
4290 
4291   `MatCopy()` copies the matrix entries of a matrix to another existing
4292   matrix (after first zeroing the second matrix).  A related routine is
4293   `MatConvert()`, which first creates a new matrix and then copies the data.
4294 
4295 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4296 @*/
4297 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4298 {
4299   PetscInt i;
4300 
4301   PetscFunctionBegin;
4302   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4303   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4304   PetscValidType(A, 1);
4305   PetscValidType(B, 2);
4306   PetscCheckSameComm(A, 1, B, 2);
4307   MatCheckPreallocated(B, 2);
4308   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4309   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4310   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,
4311              A->cmap->N, B->cmap->N);
4312   MatCheckPreallocated(A, 1);
4313   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4314 
4315   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4316   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4317   else PetscCall(MatCopy_Basic(A, B, str));
4318 
4319   B->stencil.dim = A->stencil.dim;
4320   B->stencil.noc = A->stencil.noc;
4321   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4322     B->stencil.dims[i]   = A->stencil.dims[i];
4323     B->stencil.starts[i] = A->stencil.starts[i];
4324   }
4325 
4326   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4327   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4328   PetscFunctionReturn(PETSC_SUCCESS);
4329 }
4330 
4331 /*@
4332   MatConvert - Converts a matrix to another matrix, either of the same
4333   or different type.
4334 
4335   Collective
4336 
4337   Input Parameters:
4338 + mat     - the matrix
4339 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4340             same type as the original matrix.
4341 - reuse   - denotes if the destination matrix is to be created or reused.
4342             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
4343             `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).
4344 
4345   Output Parameter:
4346 . M - pointer to place new matrix
4347 
4348   Level: intermediate
4349 
4350   Notes:
4351   `MatConvert()` first creates a new matrix and then copies the data from
4352   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4353   entries of one matrix to another already existing matrix context.
4354 
4355   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4356   the MPI communicator of the generated matrix is always the same as the communicator
4357   of the input matrix.
4358 
4359 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4360 @*/
4361 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4362 {
4363   PetscBool  sametype, issame, flg;
4364   PetscBool3 issymmetric, ishermitian;
4365   char       convname[256], mtype[256];
4366   Mat        B;
4367 
4368   PetscFunctionBegin;
4369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4370   PetscValidType(mat, 1);
4371   PetscAssertPointer(M, 4);
4372   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4373   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4374   MatCheckPreallocated(mat, 1);
4375 
4376   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4377   if (flg) newtype = mtype;
4378 
4379   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4380   PetscCall(PetscStrcmp(newtype, "same", &issame));
4381   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4382   if (reuse == MAT_REUSE_MATRIX) {
4383     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4384     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4385   }
4386 
4387   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4388     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4389     PetscFunctionReturn(PETSC_SUCCESS);
4390   }
4391 
4392   /* Cache Mat options because some converters use MatHeaderReplace  */
4393   issymmetric = mat->symmetric;
4394   ishermitian = mat->hermitian;
4395 
4396   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4397     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4398     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4399   } else {
4400     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4401     const char *prefix[3]                                 = {"seq", "mpi", ""};
4402     PetscInt    i;
4403     /*
4404        Order of precedence:
4405        0) See if newtype is a superclass of the current matrix.
4406        1) See if a specialized converter is known to the current matrix.
4407        2) See if a specialized converter is known to the desired matrix class.
4408        3) See if a good general converter is registered for the desired class
4409           (as of 6/27/03 only MATMPIADJ falls into this category).
4410        4) See if a good general converter is known for the current matrix.
4411        5) Use a really basic converter.
4412     */
4413 
4414     /* 0) See if newtype is a superclass of the current matrix.
4415           i.e mat is mpiaij and newtype is aij */
4416     for (i = 0; i < 2; i++) {
4417       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4418       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4419       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4420       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4421       if (flg) {
4422         if (reuse == MAT_INPLACE_MATRIX) {
4423           PetscCall(PetscInfo(mat, "Early return\n"));
4424           PetscFunctionReturn(PETSC_SUCCESS);
4425         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4426           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4427           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4428           PetscFunctionReturn(PETSC_SUCCESS);
4429         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4430           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4431           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4432           PetscFunctionReturn(PETSC_SUCCESS);
4433         }
4434       }
4435     }
4436     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4437     for (i = 0; i < 3; i++) {
4438       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4439       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4440       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4441       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4442       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4443       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4444       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4445       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4446       if (conv) goto foundconv;
4447     }
4448 
4449     /* 2)  See if a specialized converter is known to the desired matrix class. */
4450     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4451     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4452     PetscCall(MatSetType(B, newtype));
4453     for (i = 0; i < 3; i++) {
4454       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4455       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4456       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4457       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4458       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4459       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4460       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4461       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4462       if (conv) {
4463         PetscCall(MatDestroy(&B));
4464         goto foundconv;
4465       }
4466     }
4467 
4468     /* 3) See if a good general converter is registered for the desired class */
4469     conv = B->ops->convertfrom;
4470     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4471     PetscCall(MatDestroy(&B));
4472     if (conv) goto foundconv;
4473 
4474     /* 4) See if a good general converter is known for the current matrix */
4475     if (mat->ops->convert) conv = mat->ops->convert;
4476     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4477     if (conv) goto foundconv;
4478 
4479     /* 5) Use a really basic converter. */
4480     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4481     conv = MatConvert_Basic;
4482 
4483   foundconv:
4484     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4485     PetscCall((*conv)(mat, newtype, reuse, M));
4486     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4487       /* the block sizes must be same if the mappings are copied over */
4488       (*M)->rmap->bs = mat->rmap->bs;
4489       (*M)->cmap->bs = mat->cmap->bs;
4490       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4491       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4492       (*M)->rmap->mapping = mat->rmap->mapping;
4493       (*M)->cmap->mapping = mat->cmap->mapping;
4494     }
4495     (*M)->stencil.dim = mat->stencil.dim;
4496     (*M)->stencil.noc = mat->stencil.noc;
4497     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4498       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4499       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4500     }
4501     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4502   }
4503   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4504 
4505   /* Copy Mat options */
4506   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4507   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4508   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4509   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4510   PetscFunctionReturn(PETSC_SUCCESS);
4511 }
4512 
4513 /*@
4514   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4515 
4516   Not Collective
4517 
4518   Input Parameter:
4519 . mat - the matrix, must be a factored matrix
4520 
4521   Output Parameter:
4522 . type - the string name of the package (do not free this string)
4523 
4524   Level: intermediate
4525 
4526   Fortran Note:
4527   Pass in an empty string that is long enough and the package name will be copied into it.
4528 
4529 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4530 @*/
4531 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4532 {
4533   PetscErrorCode (*conv)(Mat, MatSolverType *);
4534 
4535   PetscFunctionBegin;
4536   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4537   PetscValidType(mat, 1);
4538   PetscAssertPointer(type, 2);
4539   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4540   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4541   if (conv) PetscCall((*conv)(mat, type));
4542   else *type = MATSOLVERPETSC;
4543   PetscFunctionReturn(PETSC_SUCCESS);
4544 }
4545 
4546 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4547 struct _MatSolverTypeForSpecifcType {
4548   MatType mtype;
4549   /* no entry for MAT_FACTOR_NONE */
4550   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4551   MatSolverTypeForSpecifcType next;
4552 };
4553 
4554 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4555 struct _MatSolverTypeHolder {
4556   char                       *name;
4557   MatSolverTypeForSpecifcType handlers;
4558   MatSolverTypeHolder         next;
4559 };
4560 
4561 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4562 
4563 /*@C
4564   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4565 
4566   Logically Collective, No Fortran Support
4567 
4568   Input Parameters:
4569 + package      - name of the package, for example petsc or superlu
4570 . mtype        - the matrix type that works with this package
4571 . ftype        - the type of factorization supported by the package
4572 - createfactor - routine that will create the factored matrix ready to be used
4573 
4574   Level: developer
4575 
4576 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4577   `MatGetFactor()`
4578 @*/
4579 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4580 {
4581   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4582   PetscBool                   flg;
4583   MatSolverTypeForSpecifcType inext, iprev = NULL;
4584 
4585   PetscFunctionBegin;
4586   PetscCall(MatInitializePackage());
4587   if (!next) {
4588     PetscCall(PetscNew(&MatSolverTypeHolders));
4589     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4590     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4591     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4592     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4593     PetscFunctionReturn(PETSC_SUCCESS);
4594   }
4595   while (next) {
4596     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4597     if (flg) {
4598       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4599       inext = next->handlers;
4600       while (inext) {
4601         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4602         if (flg) {
4603           inext->createfactor[(int)ftype - 1] = createfactor;
4604           PetscFunctionReturn(PETSC_SUCCESS);
4605         }
4606         iprev = inext;
4607         inext = inext->next;
4608       }
4609       PetscCall(PetscNew(&iprev->next));
4610       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4611       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4612       PetscFunctionReturn(PETSC_SUCCESS);
4613     }
4614     prev = next;
4615     next = next->next;
4616   }
4617   PetscCall(PetscNew(&prev->next));
4618   PetscCall(PetscStrallocpy(package, &prev->next->name));
4619   PetscCall(PetscNew(&prev->next->handlers));
4620   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4621   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4622   PetscFunctionReturn(PETSC_SUCCESS);
4623 }
4624 
4625 /*@C
4626   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4627 
4628   Input Parameters:
4629 + 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
4630 . ftype - the type of factorization supported by the type
4631 - mtype - the matrix type that works with this type
4632 
4633   Output Parameters:
4634 + foundtype    - `PETSC_TRUE` if the type was registered
4635 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4636 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4637 
4638   Calling sequence of `createfactor`:
4639 + A     - the matrix providing the factor matrix
4640 . ftype - the `MatFactorType` of the factor requested
4641 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4642 
4643   Level: developer
4644 
4645   Note:
4646   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4647   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4648   For example if one configuration had `--download-mumps` while a different one had `--download-superlu_dist`.
4649 
4650 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4651           `MatInitializePackage()`
4652 @*/
4653 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType ftype, Mat *B))
4654 {
4655   MatSolverTypeHolder         next = MatSolverTypeHolders;
4656   PetscBool                   flg;
4657   MatSolverTypeForSpecifcType inext;
4658 
4659   PetscFunctionBegin;
4660   if (foundtype) *foundtype = PETSC_FALSE;
4661   if (foundmtype) *foundmtype = PETSC_FALSE;
4662   if (createfactor) *createfactor = NULL;
4663 
4664   if (type) {
4665     while (next) {
4666       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4667       if (flg) {
4668         if (foundtype) *foundtype = PETSC_TRUE;
4669         inext = next->handlers;
4670         while (inext) {
4671           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4672           if (flg) {
4673             if (foundmtype) *foundmtype = PETSC_TRUE;
4674             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4675             PetscFunctionReturn(PETSC_SUCCESS);
4676           }
4677           inext = inext->next;
4678         }
4679       }
4680       next = next->next;
4681     }
4682   } else {
4683     while (next) {
4684       inext = next->handlers;
4685       while (inext) {
4686         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4687         if (flg && inext->createfactor[(int)ftype - 1]) {
4688           if (foundtype) *foundtype = PETSC_TRUE;
4689           if (foundmtype) *foundmtype = PETSC_TRUE;
4690           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4691           PetscFunctionReturn(PETSC_SUCCESS);
4692         }
4693         inext = inext->next;
4694       }
4695       next = next->next;
4696     }
4697     /* try with base classes inext->mtype */
4698     next = MatSolverTypeHolders;
4699     while (next) {
4700       inext = next->handlers;
4701       while (inext) {
4702         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4703         if (flg && inext->createfactor[(int)ftype - 1]) {
4704           if (foundtype) *foundtype = PETSC_TRUE;
4705           if (foundmtype) *foundmtype = PETSC_TRUE;
4706           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4707           PetscFunctionReturn(PETSC_SUCCESS);
4708         }
4709         inext = inext->next;
4710       }
4711       next = next->next;
4712     }
4713   }
4714   PetscFunctionReturn(PETSC_SUCCESS);
4715 }
4716 
4717 PetscErrorCode MatSolverTypeDestroy(void)
4718 {
4719   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4720   MatSolverTypeForSpecifcType inext, iprev;
4721 
4722   PetscFunctionBegin;
4723   while (next) {
4724     PetscCall(PetscFree(next->name));
4725     inext = next->handlers;
4726     while (inext) {
4727       PetscCall(PetscFree(inext->mtype));
4728       iprev = inext;
4729       inext = inext->next;
4730       PetscCall(PetscFree(iprev));
4731     }
4732     prev = next;
4733     next = next->next;
4734     PetscCall(PetscFree(prev));
4735   }
4736   MatSolverTypeHolders = NULL;
4737   PetscFunctionReturn(PETSC_SUCCESS);
4738 }
4739 
4740 /*@
4741   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4742 
4743   Logically Collective
4744 
4745   Input Parameter:
4746 . mat - the matrix
4747 
4748   Output Parameter:
4749 . flg - `PETSC_TRUE` if uses the ordering
4750 
4751   Level: developer
4752 
4753   Note:
4754   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4755   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4756 
4757 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4758 @*/
4759 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4760 {
4761   PetscFunctionBegin;
4762   *flg = mat->canuseordering;
4763   PetscFunctionReturn(PETSC_SUCCESS);
4764 }
4765 
4766 /*@
4767   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4768 
4769   Logically Collective
4770 
4771   Input Parameters:
4772 + mat   - the matrix obtained with `MatGetFactor()`
4773 - ftype - the factorization type to be used
4774 
4775   Output Parameter:
4776 . otype - the preferred ordering type
4777 
4778   Level: developer
4779 
4780 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4781 @*/
4782 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4783 {
4784   PetscFunctionBegin;
4785   *otype = mat->preferredordering[ftype];
4786   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4787   PetscFunctionReturn(PETSC_SUCCESS);
4788 }
4789 
4790 /*@
4791   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4792 
4793   Collective
4794 
4795   Input Parameters:
4796 + mat   - the matrix
4797 . 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
4798           the other criteria is returned
4799 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4800 
4801   Output Parameter:
4802 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4803 
4804   Options Database Keys:
4805 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4806 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4807                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4808 
4809   Level: intermediate
4810 
4811   Notes:
4812   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4813   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4814 
4815   Users usually access the factorization solvers via `KSP`
4816 
4817   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4818   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
4819 
4820   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4821   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4822   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4823 
4824   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4825   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4826   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4827 
4828   Developer Note:
4829   This should actually be called `MatCreateFactor()` since it creates a new factor object
4830 
4831 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4832           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4833           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4834 @*/
4835 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4836 {
4837   PetscBool foundtype, foundmtype, shell, hasop = PETSC_FALSE;
4838   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4839 
4840   PetscFunctionBegin;
4841   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4842   PetscValidType(mat, 1);
4843 
4844   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4845   MatCheckPreallocated(mat, 1);
4846 
4847   PetscCall(MatIsShell(mat, &shell));
4848   if (shell) PetscCall(MatHasOperation(mat, MATOP_GET_FACTOR, &hasop));
4849   if (hasop) {
4850     PetscUseTypeMethod(mat, getfactor, type, ftype, f);
4851     PetscFunctionReturn(PETSC_SUCCESS);
4852   }
4853 
4854   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4855   if (!foundtype) {
4856     if (type) {
4857       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],
4858               ((PetscObject)mat)->type_name, type);
4859     } else {
4860       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);
4861     }
4862   }
4863   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4864   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);
4865 
4866   PetscCall((*conv)(mat, ftype, f));
4867   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4868   PetscFunctionReturn(PETSC_SUCCESS);
4869 }
4870 
4871 /*@
4872   MatGetFactorAvailable - Returns a flag if matrix supports particular type and factor type
4873 
4874   Not Collective
4875 
4876   Input Parameters:
4877 + mat   - the matrix
4878 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4879 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4880 
4881   Output Parameter:
4882 . flg - PETSC_TRUE if the factorization is available
4883 
4884   Level: intermediate
4885 
4886   Notes:
4887   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4888   such as pastix, superlu, mumps etc.
4889 
4890   PETSc must have been ./configure to use the external solver, using the option --download-package
4891 
4892   Developer Note:
4893   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4894 
4895 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4896           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4897 @*/
4898 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4899 {
4900   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4901 
4902   PetscFunctionBegin;
4903   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4904   PetscAssertPointer(flg, 4);
4905 
4906   *flg = PETSC_FALSE;
4907   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4908 
4909   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4910   MatCheckPreallocated(mat, 1);
4911 
4912   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4913   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4914   PetscFunctionReturn(PETSC_SUCCESS);
4915 }
4916 
4917 /*@
4918   MatDuplicate - Duplicates a matrix including the non-zero structure.
4919 
4920   Collective
4921 
4922   Input Parameters:
4923 + mat - the matrix
4924 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4925         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4926 
4927   Output Parameter:
4928 . M - pointer to place new matrix
4929 
4930   Level: intermediate
4931 
4932   Notes:
4933   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4934 
4935   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4936 
4937   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.
4938 
4939   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4940   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4941   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4942 
4943 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4944 @*/
4945 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4946 {
4947   Mat         B;
4948   VecType     vtype;
4949   PetscInt    i;
4950   PetscObject dm, container_h, container_d;
4951   void (*viewf)(void);
4952 
4953   PetscFunctionBegin;
4954   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4955   PetscValidType(mat, 1);
4956   PetscAssertPointer(M, 3);
4957   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4958   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4959   MatCheckPreallocated(mat, 1);
4960 
4961   *M = NULL;
4962   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4963   PetscUseTypeMethod(mat, duplicate, op, M);
4964   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4965   B = *M;
4966 
4967   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4968   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4969   PetscCall(MatGetVecType(mat, &vtype));
4970   PetscCall(MatSetVecType(B, vtype));
4971 
4972   B->stencil.dim = mat->stencil.dim;
4973   B->stencil.noc = mat->stencil.noc;
4974   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4975     B->stencil.dims[i]   = mat->stencil.dims[i];
4976     B->stencil.starts[i] = mat->stencil.starts[i];
4977   }
4978 
4979   B->nooffproczerorows = mat->nooffproczerorows;
4980   B->nooffprocentries  = mat->nooffprocentries;
4981 
4982   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4983   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4984   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4985   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4986   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4987   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4988   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4989   PetscFunctionReturn(PETSC_SUCCESS);
4990 }
4991 
4992 /*@
4993   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4994 
4995   Logically Collective
4996 
4997   Input Parameter:
4998 . mat - the matrix
4999 
5000   Output Parameter:
5001 . v - the diagonal of the matrix
5002 
5003   Level: intermediate
5004 
5005   Note:
5006   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
5007   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
5008   is larger than `ndiag`, the values of the remaining entries are unspecified.
5009 
5010   Currently only correct in parallel for square matrices.
5011 
5012 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
5013 @*/
5014 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
5015 {
5016   PetscFunctionBegin;
5017   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5018   PetscValidType(mat, 1);
5019   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5020   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5021   MatCheckPreallocated(mat, 1);
5022   if (PetscDefined(USE_DEBUG)) {
5023     PetscInt nv, row, col, ndiag;
5024 
5025     PetscCall(VecGetLocalSize(v, &nv));
5026     PetscCall(MatGetLocalSize(mat, &row, &col));
5027     ndiag = PetscMin(row, col);
5028     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);
5029   }
5030 
5031   PetscUseTypeMethod(mat, getdiagonal, v);
5032   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5033   PetscFunctionReturn(PETSC_SUCCESS);
5034 }
5035 
5036 /*@
5037   MatGetRowMin - Gets the minimum value (of the real part) of each
5038   row of the matrix
5039 
5040   Logically Collective
5041 
5042   Input Parameter:
5043 . mat - the matrix
5044 
5045   Output Parameters:
5046 + v   - the vector for storing the maximums
5047 - idx - the indices of the column found for each row (optional, pass `NULL` if not needed)
5048 
5049   Level: intermediate
5050 
5051   Note:
5052   The result of this call are the same as if one converted the matrix to dense format
5053   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5054 
5055   This code is only implemented for a couple of matrix formats.
5056 
5057 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
5058           `MatGetRowMax()`
5059 @*/
5060 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
5061 {
5062   PetscFunctionBegin;
5063   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5064   PetscValidType(mat, 1);
5065   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5066   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5067 
5068   if (!mat->cmap->N) {
5069     PetscCall(VecSet(v, PETSC_MAX_REAL));
5070     if (idx) {
5071       PetscInt i, m = mat->rmap->n;
5072       for (i = 0; i < m; i++) idx[i] = -1;
5073     }
5074   } else {
5075     MatCheckPreallocated(mat, 1);
5076   }
5077   PetscUseTypeMethod(mat, getrowmin, v, idx);
5078   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5079   PetscFunctionReturn(PETSC_SUCCESS);
5080 }
5081 
5082 /*@
5083   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5084   row of the matrix
5085 
5086   Logically Collective
5087 
5088   Input Parameter:
5089 . mat - the matrix
5090 
5091   Output Parameters:
5092 + v   - the vector for storing the minimums
5093 - idx - the indices of the column found for each row (or `NULL` if not needed)
5094 
5095   Level: intermediate
5096 
5097   Notes:
5098   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5099   row is 0 (the first column).
5100 
5101   This code is only implemented for a couple of matrix formats.
5102 
5103 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5104 @*/
5105 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5106 {
5107   PetscFunctionBegin;
5108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5109   PetscValidType(mat, 1);
5110   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5111   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5112   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5113 
5114   if (!mat->cmap->N) {
5115     PetscCall(VecSet(v, 0.0));
5116     if (idx) {
5117       PetscInt i, m = mat->rmap->n;
5118       for (i = 0; i < m; i++) idx[i] = -1;
5119     }
5120   } else {
5121     MatCheckPreallocated(mat, 1);
5122     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5123     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5124   }
5125   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5126   PetscFunctionReturn(PETSC_SUCCESS);
5127 }
5128 
5129 /*@
5130   MatGetRowMax - Gets the maximum value (of the real part) of each
5131   row of the matrix
5132 
5133   Logically Collective
5134 
5135   Input Parameter:
5136 . mat - the matrix
5137 
5138   Output Parameters:
5139 + v   - the vector for storing the maximums
5140 - idx - the indices of the column found for each row (optional, otherwise pass `NULL`)
5141 
5142   Level: intermediate
5143 
5144   Notes:
5145   The result of this call are the same as if one converted the matrix to dense format
5146   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5147 
5148   This code is only implemented for a couple of matrix formats.
5149 
5150 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5151 @*/
5152 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5153 {
5154   PetscFunctionBegin;
5155   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5156   PetscValidType(mat, 1);
5157   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5158   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5159 
5160   if (!mat->cmap->N) {
5161     PetscCall(VecSet(v, PETSC_MIN_REAL));
5162     if (idx) {
5163       PetscInt i, m = mat->rmap->n;
5164       for (i = 0; i < m; i++) idx[i] = -1;
5165     }
5166   } else {
5167     MatCheckPreallocated(mat, 1);
5168     PetscUseTypeMethod(mat, getrowmax, v, idx);
5169   }
5170   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5171   PetscFunctionReturn(PETSC_SUCCESS);
5172 }
5173 
5174 /*@
5175   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5176   row of the matrix
5177 
5178   Logically Collective
5179 
5180   Input Parameter:
5181 . mat - the matrix
5182 
5183   Output Parameters:
5184 + v   - the vector for storing the maximums
5185 - idx - the indices of the column found for each row (or `NULL` if not needed)
5186 
5187   Level: intermediate
5188 
5189   Notes:
5190   if a row is completely empty or has only 0.0 values, then the `idx` value for that
5191   row is 0 (the first column).
5192 
5193   This code is only implemented for a couple of matrix formats.
5194 
5195 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5196 @*/
5197 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5198 {
5199   PetscFunctionBegin;
5200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5201   PetscValidType(mat, 1);
5202   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5203   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5204 
5205   if (!mat->cmap->N) {
5206     PetscCall(VecSet(v, 0.0));
5207     if (idx) {
5208       PetscInt i, m = mat->rmap->n;
5209       for (i = 0; i < m; i++) idx[i] = -1;
5210     }
5211   } else {
5212     MatCheckPreallocated(mat, 1);
5213     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5214     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5215   }
5216   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5217   PetscFunctionReturn(PETSC_SUCCESS);
5218 }
5219 
5220 /*@
5221   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5222 
5223   Logically Collective
5224 
5225   Input Parameter:
5226 . mat - the matrix
5227 
5228   Output Parameter:
5229 . v - the vector for storing the sum
5230 
5231   Level: intermediate
5232 
5233   This code is only implemented for a couple of matrix formats.
5234 
5235 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5236 @*/
5237 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5238 {
5239   PetscFunctionBegin;
5240   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5241   PetscValidType(mat, 1);
5242   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5243   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5244 
5245   if (!mat->cmap->N) {
5246     PetscCall(VecSet(v, 0.0));
5247   } else {
5248     MatCheckPreallocated(mat, 1);
5249     PetscUseTypeMethod(mat, getrowsumabs, v);
5250   }
5251   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5252   PetscFunctionReturn(PETSC_SUCCESS);
5253 }
5254 
5255 /*@
5256   MatGetRowSum - Gets the sum of each row of the matrix
5257 
5258   Logically or Neighborhood Collective
5259 
5260   Input Parameter:
5261 . mat - the matrix
5262 
5263   Output Parameter:
5264 . v - the vector for storing the sum of rows
5265 
5266   Level: intermediate
5267 
5268   Note:
5269   This code is slow since it is not currently specialized for different formats
5270 
5271 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5272 @*/
5273 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5274 {
5275   Vec ones;
5276 
5277   PetscFunctionBegin;
5278   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5279   PetscValidType(mat, 1);
5280   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5281   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5282   MatCheckPreallocated(mat, 1);
5283   PetscCall(MatCreateVecs(mat, &ones, NULL));
5284   PetscCall(VecSet(ones, 1.));
5285   PetscCall(MatMult(mat, ones, v));
5286   PetscCall(VecDestroy(&ones));
5287   PetscFunctionReturn(PETSC_SUCCESS);
5288 }
5289 
5290 /*@
5291   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5292   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5293 
5294   Collective
5295 
5296   Input Parameter:
5297 . mat - the matrix to provide the transpose
5298 
5299   Output Parameter:
5300 . 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
5301 
5302   Level: advanced
5303 
5304   Note:
5305   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
5306   routine allows bypassing that call.
5307 
5308 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5309 @*/
5310 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5311 {
5312   PetscContainer  rB = NULL;
5313   MatParentState *rb = NULL;
5314 
5315   PetscFunctionBegin;
5316   PetscCall(PetscNew(&rb));
5317   rb->id    = ((PetscObject)mat)->id;
5318   rb->state = 0;
5319   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5320   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5321   PetscCall(PetscContainerSetPointer(rB, rb));
5322   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5323   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5324   PetscCall(PetscObjectDereference((PetscObject)rB));
5325   PetscFunctionReturn(PETSC_SUCCESS);
5326 }
5327 
5328 /*@
5329   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5330 
5331   Collective
5332 
5333   Input Parameters:
5334 + mat   - the matrix to transpose
5335 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5336 
5337   Output Parameter:
5338 . B - the transpose
5339 
5340   Level: intermediate
5341 
5342   Notes:
5343   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5344 
5345   `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
5346   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5347 
5348   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.
5349 
5350   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5351 
5352   If mat is unchanged from the last call this function returns immediately without recomputing the result
5353 
5354   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5355 
5356 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5357           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5358 @*/
5359 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5360 {
5361   PetscContainer  rB = NULL;
5362   MatParentState *rb = NULL;
5363 
5364   PetscFunctionBegin;
5365   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5366   PetscValidType(mat, 1);
5367   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5368   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5369   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5370   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5371   MatCheckPreallocated(mat, 1);
5372   if (reuse == MAT_REUSE_MATRIX) {
5373     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5374     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5375     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5376     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5377     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5378   }
5379 
5380   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5381   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5382     PetscUseTypeMethod(mat, transpose, reuse, B);
5383     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5384   }
5385   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5386 
5387   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5388   if (reuse != MAT_INPLACE_MATRIX) {
5389     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5390     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5391     rb->state        = ((PetscObject)mat)->state;
5392     rb->nonzerostate = mat->nonzerostate;
5393   }
5394   PetscFunctionReturn(PETSC_SUCCESS);
5395 }
5396 
5397 /*@
5398   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5399 
5400   Collective
5401 
5402   Input Parameter:
5403 . A - the matrix to transpose
5404 
5405   Output Parameter:
5406 . 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
5407       numerical portion.
5408 
5409   Level: intermediate
5410 
5411   Note:
5412   This is not supported for many matrix types, use `MatTranspose()` in those cases
5413 
5414 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5415 @*/
5416 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5417 {
5418   PetscFunctionBegin;
5419   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5420   PetscValidType(A, 1);
5421   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5422   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5423   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5424   PetscUseTypeMethod(A, transposesymbolic, B);
5425   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5426 
5427   PetscCall(MatTransposeSetPrecursor(A, *B));
5428   PetscFunctionReturn(PETSC_SUCCESS);
5429 }
5430 
5431 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5432 {
5433   PetscContainer  rB;
5434   MatParentState *rb;
5435 
5436   PetscFunctionBegin;
5437   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5438   PetscValidType(A, 1);
5439   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5440   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5441   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5442   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5443   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5444   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5445   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5446   PetscFunctionReturn(PETSC_SUCCESS);
5447 }
5448 
5449 /*@
5450   MatIsTranspose - Test whether a matrix is another one's transpose,
5451   or its own, in which case it tests symmetry.
5452 
5453   Collective
5454 
5455   Input Parameters:
5456 + A   - the matrix to test
5457 . B   - the matrix to test against, this can equal the first parameter
5458 - tol - tolerance, differences between entries smaller than this are counted as zero
5459 
5460   Output Parameter:
5461 . flg - the result
5462 
5463   Level: intermediate
5464 
5465   Notes:
5466   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5467   test involves parallel copies of the block off-diagonal parts of the matrix.
5468 
5469 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5470 @*/
5471 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5472 {
5473   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5474 
5475   PetscFunctionBegin;
5476   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5477   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5478   PetscAssertPointer(flg, 4);
5479   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5480   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5481   *flg = PETSC_FALSE;
5482   if (f && g) {
5483     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5484     PetscCall((*f)(A, B, tol, flg));
5485   } else {
5486     MatType mattype;
5487 
5488     PetscCall(MatGetType(f ? B : A, &mattype));
5489     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5490   }
5491   PetscFunctionReturn(PETSC_SUCCESS);
5492 }
5493 
5494 /*@
5495   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5496 
5497   Collective
5498 
5499   Input Parameters:
5500 + mat   - the matrix to transpose and complex conjugate
5501 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5502 
5503   Output Parameter:
5504 . B - the Hermitian transpose
5505 
5506   Level: intermediate
5507 
5508 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5509 @*/
5510 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5511 {
5512   PetscFunctionBegin;
5513   PetscCall(MatTranspose(mat, reuse, B));
5514 #if defined(PETSC_USE_COMPLEX)
5515   PetscCall(MatConjugate(*B));
5516 #endif
5517   PetscFunctionReturn(PETSC_SUCCESS);
5518 }
5519 
5520 /*@
5521   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5522 
5523   Collective
5524 
5525   Input Parameters:
5526 + A   - the matrix to test
5527 . B   - the matrix to test against, this can equal the first parameter
5528 - tol - tolerance, differences between entries smaller than this are counted as zero
5529 
5530   Output Parameter:
5531 . flg - the result
5532 
5533   Level: intermediate
5534 
5535   Notes:
5536   Only available for `MATAIJ` matrices.
5537 
5538   The sequential algorithm
5539   has a running time of the order of the number of nonzeros; the parallel
5540   test involves parallel copies of the block off-diagonal parts of the matrix.
5541 
5542 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5543 @*/
5544 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5545 {
5546   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5547 
5548   PetscFunctionBegin;
5549   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5550   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5551   PetscAssertPointer(flg, 4);
5552   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5553   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5554   if (f && g) {
5555     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5556     PetscCall((*f)(A, B, tol, flg));
5557   }
5558   PetscFunctionReturn(PETSC_SUCCESS);
5559 }
5560 
5561 /*@
5562   MatPermute - Creates a new matrix with rows and columns permuted from the
5563   original.
5564 
5565   Collective
5566 
5567   Input Parameters:
5568 + mat - the matrix to permute
5569 . row - row permutation, each processor supplies only the permutation for its rows
5570 - col - column permutation, each processor supplies only the permutation for its columns
5571 
5572   Output Parameter:
5573 . B - the permuted matrix
5574 
5575   Level: advanced
5576 
5577   Note:
5578   The index sets map from row/col of permuted matrix to row/col of original matrix.
5579   The index sets should be on the same communicator as mat and have the same local sizes.
5580 
5581   Developer Note:
5582   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5583   exploit the fact that row and col are permutations, consider implementing the
5584   more general `MatCreateSubMatrix()` instead.
5585 
5586 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5587 @*/
5588 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5589 {
5590   PetscFunctionBegin;
5591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5592   PetscValidType(mat, 1);
5593   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5594   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5595   PetscAssertPointer(B, 4);
5596   PetscCheckSameComm(mat, 1, row, 2);
5597   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5598   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5599   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5600   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5601   MatCheckPreallocated(mat, 1);
5602 
5603   if (mat->ops->permute) {
5604     PetscUseTypeMethod(mat, permute, row, col, B);
5605     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5606   } else {
5607     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5608   }
5609   PetscFunctionReturn(PETSC_SUCCESS);
5610 }
5611 
5612 /*@
5613   MatEqual - Compares two matrices.
5614 
5615   Collective
5616 
5617   Input Parameters:
5618 + A - the first matrix
5619 - B - the second matrix
5620 
5621   Output Parameter:
5622 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5623 
5624   Level: intermediate
5625 
5626 .seealso: [](ch_matrices), `Mat`
5627 @*/
5628 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5629 {
5630   PetscFunctionBegin;
5631   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5632   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5633   PetscValidType(A, 1);
5634   PetscValidType(B, 2);
5635   PetscAssertPointer(flg, 3);
5636   PetscCheckSameComm(A, 1, B, 2);
5637   MatCheckPreallocated(A, 1);
5638   MatCheckPreallocated(B, 2);
5639   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5640   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5641   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,
5642              B->cmap->N);
5643   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5644     PetscUseTypeMethod(A, equal, B, flg);
5645   } else {
5646     PetscCall(MatMultEqual(A, B, 10, flg));
5647   }
5648   PetscFunctionReturn(PETSC_SUCCESS);
5649 }
5650 
5651 /*@
5652   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5653   matrices that are stored as vectors.  Either of the two scaling
5654   matrices can be `NULL`.
5655 
5656   Collective
5657 
5658   Input Parameters:
5659 + mat - the matrix to be scaled
5660 . l   - the left scaling vector (or `NULL`)
5661 - r   - the right scaling vector (or `NULL`)
5662 
5663   Level: intermediate
5664 
5665   Note:
5666   `MatDiagonalScale()` computes $A = LAR$, where
5667   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5668   The L scales the rows of the matrix, the R scales the columns of the matrix.
5669 
5670 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5671 @*/
5672 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5673 {
5674   PetscFunctionBegin;
5675   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5676   PetscValidType(mat, 1);
5677   if (l) {
5678     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5679     PetscCheckSameComm(mat, 1, l, 2);
5680   }
5681   if (r) {
5682     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5683     PetscCheckSameComm(mat, 1, r, 3);
5684   }
5685   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5686   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5687   MatCheckPreallocated(mat, 1);
5688   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5689 
5690   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5691   PetscUseTypeMethod(mat, diagonalscale, l, r);
5692   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5693   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5694   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5695   PetscFunctionReturn(PETSC_SUCCESS);
5696 }
5697 
5698 /*@
5699   MatScale - Scales all elements of a matrix by a given number.
5700 
5701   Logically Collective
5702 
5703   Input Parameters:
5704 + mat - the matrix to be scaled
5705 - a   - the scaling value
5706 
5707   Level: intermediate
5708 
5709 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5710 @*/
5711 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5712 {
5713   PetscFunctionBegin;
5714   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5715   PetscValidType(mat, 1);
5716   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5717   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5718   PetscValidLogicalCollectiveScalar(mat, a, 2);
5719   MatCheckPreallocated(mat, 1);
5720 
5721   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5722   if (a != (PetscScalar)1.0) {
5723     PetscUseTypeMethod(mat, scale, a);
5724     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5725   }
5726   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5727   PetscFunctionReturn(PETSC_SUCCESS);
5728 }
5729 
5730 /*@
5731   MatNorm - Calculates various norms of a matrix.
5732 
5733   Collective
5734 
5735   Input Parameters:
5736 + mat  - the matrix
5737 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5738 
5739   Output Parameter:
5740 . nrm - the resulting norm
5741 
5742   Level: intermediate
5743 
5744 .seealso: [](ch_matrices), `Mat`
5745 @*/
5746 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5747 {
5748   PetscFunctionBegin;
5749   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5750   PetscValidType(mat, 1);
5751   PetscAssertPointer(nrm, 3);
5752 
5753   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5754   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5755   MatCheckPreallocated(mat, 1);
5756 
5757   PetscUseTypeMethod(mat, norm, type, nrm);
5758   PetscFunctionReturn(PETSC_SUCCESS);
5759 }
5760 
5761 /*
5762      This variable is used to prevent counting of MatAssemblyBegin() that
5763    are called from within a MatAssemblyEnd().
5764 */
5765 static PetscInt MatAssemblyEnd_InUse = 0;
5766 /*@
5767   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5768   be called after completing all calls to `MatSetValues()`.
5769 
5770   Collective
5771 
5772   Input Parameters:
5773 + mat  - the matrix
5774 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5775 
5776   Level: beginner
5777 
5778   Notes:
5779   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5780   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5781 
5782   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5783   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5784   using the matrix.
5785 
5786   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5787   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
5788   a global collective operation requiring all processes that share the matrix.
5789 
5790   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5791   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5792   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5793 
5794 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5795 @*/
5796 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5797 {
5798   PetscFunctionBegin;
5799   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5800   PetscValidType(mat, 1);
5801   MatCheckPreallocated(mat, 1);
5802   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix. Did you forget to call MatSetUnfactored()?");
5803   if (mat->assembled) {
5804     mat->was_assembled = PETSC_TRUE;
5805     mat->assembled     = PETSC_FALSE;
5806   }
5807 
5808   if (!MatAssemblyEnd_InUse) {
5809     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5810     PetscTryTypeMethod(mat, assemblybegin, type);
5811     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5812   } else PetscTryTypeMethod(mat, assemblybegin, type);
5813   PetscFunctionReturn(PETSC_SUCCESS);
5814 }
5815 
5816 /*@
5817   MatAssembled - Indicates if a matrix has been assembled and is ready for
5818   use; for example, in matrix-vector product.
5819 
5820   Not Collective
5821 
5822   Input Parameter:
5823 . mat - the matrix
5824 
5825   Output Parameter:
5826 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5827 
5828   Level: advanced
5829 
5830 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5831 @*/
5832 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5833 {
5834   PetscFunctionBegin;
5835   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5836   PetscAssertPointer(assembled, 2);
5837   *assembled = mat->assembled;
5838   PetscFunctionReturn(PETSC_SUCCESS);
5839 }
5840 
5841 /*@
5842   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5843   be called after `MatAssemblyBegin()`.
5844 
5845   Collective
5846 
5847   Input Parameters:
5848 + mat  - the matrix
5849 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5850 
5851   Options Database Keys:
5852 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5853 . -mat_view ::ascii_info_detail      - Prints more detailed info
5854 . -mat_view                          - Prints matrix in ASCII format
5855 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5856 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5857 . -display <name>                    - Sets display name (default is host)
5858 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5859 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5860 . -viewer_socket_machine <machine>   - Machine to use for socket
5861 . -viewer_socket_port <port>         - Port number to use for socket
5862 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5863 
5864   Level: beginner
5865 
5866 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5867 @*/
5868 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5869 {
5870   static PetscInt inassm = 0;
5871   PetscBool       flg    = PETSC_FALSE;
5872 
5873   PetscFunctionBegin;
5874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5875   PetscValidType(mat, 1);
5876 
5877   inassm++;
5878   MatAssemblyEnd_InUse++;
5879   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5880     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5881     PetscTryTypeMethod(mat, assemblyend, type);
5882     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5883   } else PetscTryTypeMethod(mat, assemblyend, type);
5884 
5885   /* Flush assembly is not a true assembly */
5886   if (type != MAT_FLUSH_ASSEMBLY) {
5887     if (mat->num_ass) {
5888       if (!mat->symmetry_eternal) {
5889         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5890         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5891       }
5892       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5893       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5894     }
5895     mat->num_ass++;
5896     mat->assembled        = PETSC_TRUE;
5897     mat->ass_nonzerostate = mat->nonzerostate;
5898   }
5899 
5900   mat->insertmode = NOT_SET_VALUES;
5901   MatAssemblyEnd_InUse--;
5902   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5903   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5904     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5905 
5906     if (mat->checksymmetryonassembly) {
5907       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5908       if (flg) {
5909         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5910       } else {
5911         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5912       }
5913     }
5914     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5915   }
5916   inassm--;
5917   PetscFunctionReturn(PETSC_SUCCESS);
5918 }
5919 
5920 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5921 /*@
5922   MatSetOption - Sets a parameter option for a matrix. Some options
5923   may be specific to certain storage formats.  Some options
5924   determine how values will be inserted (or added). Sorted,
5925   row-oriented input will generally assemble the fastest. The default
5926   is row-oriented.
5927 
5928   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5929 
5930   Input Parameters:
5931 + mat - the matrix
5932 . op  - the option, one of those listed below (and possibly others),
5933 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5934 
5935   Options Describing Matrix Structure:
5936 + `MAT_SPD`                         - symmetric positive definite
5937 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5938 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5939 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5940 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5941 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5942 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5943 
5944    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5945    do not need to be computed (usually at a high cost)
5946 
5947    Options For Use with `MatSetValues()`:
5948    Insert a logically dense subblock, which can be
5949 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5950 
5951    These options reflect the data you pass in with `MatSetValues()`; it has
5952    nothing to do with how the data is stored internally in the matrix
5953    data structure.
5954 
5955    When (re)assembling a matrix, we can restrict the input for
5956    efficiency/debugging purposes.  These options include
5957 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5958 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5959 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5960 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5961 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5962 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5963         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5964         performance for very large process counts.
5965 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5966         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5967         functions, instead sending only neighbor messages.
5968 
5969   Level: intermediate
5970 
5971   Notes:
5972   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5973 
5974   Some options are relevant only for particular matrix types and
5975   are thus ignored by others.  Other options are not supported by
5976   certain matrix types and will generate an error message if set.
5977 
5978   If using Fortran to compute a matrix, one may need to
5979   use the column-oriented option (or convert to the row-oriented
5980   format).
5981 
5982   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5983   that would generate a new entry in the nonzero structure is instead
5984   ignored.  Thus, if memory has not already been allocated for this particular
5985   data, then the insertion is ignored. For dense matrices, in which
5986   the entire array is allocated, no entries are ever ignored.
5987   Set after the first `MatAssemblyEnd()`. If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5988 
5989   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5990   that would generate a new entry in the nonzero structure instead produces
5991   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
5992 
5993   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5994   that would generate a new entry that has not been preallocated will
5995   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5996   only.) This is a useful flag when debugging matrix memory preallocation.
5997   If this option is set, then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5998 
5999   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
6000   other processors should be dropped, rather than stashed.
6001   This is useful if you know that the "owning" processor is also
6002   always generating the correct matrix entries, so that PETSc need
6003   not transfer duplicate entries generated on another processor.
6004 
6005   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
6006   searches during matrix assembly. When this flag is set, the hash table
6007   is created during the first matrix assembly. This hash table is
6008   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
6009   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
6010   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
6011   supported by `MATMPIBAIJ` format only.
6012 
6013   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
6014   are kept in the nonzero structure. This flag is not used for `MatZeroRowsColumns()`
6015 
6016   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
6017   a zero location in the matrix
6018 
6019   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
6020 
6021   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
6022   zero row routines and thus improves performance for very large process counts.
6023 
6024   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
6025   part of the matrix (since they should match the upper triangular part).
6026 
6027   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
6028   single call to `MatSetValues()`, preallocation is perfect, row-oriented, `INSERT_VALUES` is used. Common
6029   with finite difference schemes with non-periodic boundary conditions.
6030 
6031   Developer Note:
6032   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
6033   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
6034   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
6035   not changed.
6036 
6037 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
6038 @*/
6039 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
6040 {
6041   PetscFunctionBegin;
6042   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6043   if (op > 0) {
6044     PetscValidLogicalCollectiveEnum(mat, op, 2);
6045     PetscValidLogicalCollectiveBool(mat, flg, 3);
6046   }
6047 
6048   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);
6049 
6050   switch (op) {
6051   case MAT_FORCE_DIAGONAL_ENTRIES:
6052     mat->force_diagonals = flg;
6053     PetscFunctionReturn(PETSC_SUCCESS);
6054   case MAT_NO_OFF_PROC_ENTRIES:
6055     mat->nooffprocentries = flg;
6056     PetscFunctionReturn(PETSC_SUCCESS);
6057   case MAT_SUBSET_OFF_PROC_ENTRIES:
6058     mat->assembly_subset = flg;
6059     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
6060 #if !defined(PETSC_HAVE_MPIUNI)
6061       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6062 #endif
6063       mat->stash.first_assembly_done = PETSC_FALSE;
6064     }
6065     PetscFunctionReturn(PETSC_SUCCESS);
6066   case MAT_NO_OFF_PROC_ZERO_ROWS:
6067     mat->nooffproczerorows = flg;
6068     PetscFunctionReturn(PETSC_SUCCESS);
6069   case MAT_SPD:
6070     if (flg) {
6071       mat->spd                    = PETSC_BOOL3_TRUE;
6072       mat->symmetric              = PETSC_BOOL3_TRUE;
6073       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6074     } else {
6075       mat->spd = PETSC_BOOL3_FALSE;
6076     }
6077     break;
6078   case MAT_SYMMETRIC:
6079     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6080     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6081 #if !defined(PETSC_USE_COMPLEX)
6082     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6083 #endif
6084     break;
6085   case MAT_HERMITIAN:
6086     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6087     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6088 #if !defined(PETSC_USE_COMPLEX)
6089     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6090 #endif
6091     break;
6092   case MAT_STRUCTURALLY_SYMMETRIC:
6093     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6094     break;
6095   case MAT_SYMMETRY_ETERNAL:
6096     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");
6097     mat->symmetry_eternal = flg;
6098     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6099     break;
6100   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6101     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");
6102     mat->structural_symmetry_eternal = flg;
6103     break;
6104   case MAT_SPD_ETERNAL:
6105     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");
6106     mat->spd_eternal = flg;
6107     if (flg) {
6108       mat->structural_symmetry_eternal = PETSC_TRUE;
6109       mat->symmetry_eternal            = PETSC_TRUE;
6110     }
6111     break;
6112   case MAT_STRUCTURE_ONLY:
6113     mat->structure_only = flg;
6114     break;
6115   case MAT_SORTED_FULL:
6116     mat->sortedfull = flg;
6117     break;
6118   default:
6119     break;
6120   }
6121   PetscTryTypeMethod(mat, setoption, op, flg);
6122   PetscFunctionReturn(PETSC_SUCCESS);
6123 }
6124 
6125 /*@
6126   MatGetOption - Gets a parameter option that has been set for a matrix.
6127 
6128   Logically Collective
6129 
6130   Input Parameters:
6131 + mat - the matrix
6132 - op  - the option, this only responds to certain options, check the code for which ones
6133 
6134   Output Parameter:
6135 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6136 
6137   Level: intermediate
6138 
6139   Notes:
6140   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6141 
6142   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6143   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6144 
6145 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6146     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6147 @*/
6148 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6149 {
6150   PetscFunctionBegin;
6151   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6152   PetscValidType(mat, 1);
6153 
6154   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);
6155   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()");
6156 
6157   switch (op) {
6158   case MAT_NO_OFF_PROC_ENTRIES:
6159     *flg = mat->nooffprocentries;
6160     break;
6161   case MAT_NO_OFF_PROC_ZERO_ROWS:
6162     *flg = mat->nooffproczerorows;
6163     break;
6164   case MAT_SYMMETRIC:
6165     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6166     break;
6167   case MAT_HERMITIAN:
6168     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6169     break;
6170   case MAT_STRUCTURALLY_SYMMETRIC:
6171     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6172     break;
6173   case MAT_SPD:
6174     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6175     break;
6176   case MAT_SYMMETRY_ETERNAL:
6177     *flg = mat->symmetry_eternal;
6178     break;
6179   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6180     *flg = mat->symmetry_eternal;
6181     break;
6182   default:
6183     break;
6184   }
6185   PetscFunctionReturn(PETSC_SUCCESS);
6186 }
6187 
6188 /*@
6189   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6190   this routine retains the old nonzero structure.
6191 
6192   Logically Collective
6193 
6194   Input Parameter:
6195 . mat - the matrix
6196 
6197   Level: intermediate
6198 
6199   Note:
6200   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.
6201   See the Performance chapter of the users manual for information on preallocating matrices.
6202 
6203 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6204 @*/
6205 PetscErrorCode MatZeroEntries(Mat mat)
6206 {
6207   PetscFunctionBegin;
6208   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6209   PetscValidType(mat, 1);
6210   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6211   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");
6212   MatCheckPreallocated(mat, 1);
6213 
6214   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6215   PetscUseTypeMethod(mat, zeroentries);
6216   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6217   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6218   PetscFunctionReturn(PETSC_SUCCESS);
6219 }
6220 
6221 /*@
6222   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6223   of a set of rows and columns of a matrix.
6224 
6225   Collective
6226 
6227   Input Parameters:
6228 + mat     - the matrix
6229 . numRows - the number of rows/columns to zero
6230 . rows    - the global row indices
6231 . diag    - value put in the diagonal of the eliminated rows
6232 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6233 - b       - optional vector of the right-hand side, that will be adjusted by provided solution entries
6234 
6235   Level: intermediate
6236 
6237   Notes:
6238   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6239 
6240   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6241   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
6242 
6243   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6244   Krylov method to take advantage of the known solution on the zeroed rows.
6245 
6246   For the parallel case, all processes that share the matrix (i.e.,
6247   those in the communicator used for matrix creation) MUST call this
6248   routine, regardless of whether any rows being zeroed are owned by
6249   them.
6250 
6251   Unlike `MatZeroRows()`, this ignores the `MAT_KEEP_NONZERO_PATTERN` option value set with `MatSetOption()`, it merely zeros those entries in the matrix, but never
6252   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
6253   missing.
6254 
6255   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6256   list only rows local to itself).
6257 
6258   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6259 
6260 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6261           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6262 @*/
6263 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6264 {
6265   PetscFunctionBegin;
6266   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6267   PetscValidType(mat, 1);
6268   if (numRows) PetscAssertPointer(rows, 3);
6269   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6270   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6271   MatCheckPreallocated(mat, 1);
6272 
6273   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6274   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6275   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6276   PetscFunctionReturn(PETSC_SUCCESS);
6277 }
6278 
6279 /*@
6280   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6281   of a set of rows and columns of a matrix.
6282 
6283   Collective
6284 
6285   Input Parameters:
6286 + mat  - the matrix
6287 . is   - the rows to zero
6288 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6289 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6290 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6291 
6292   Level: intermediate
6293 
6294   Note:
6295   See `MatZeroRowsColumns()` for details on how this routine operates.
6296 
6297 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6298           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6299 @*/
6300 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6301 {
6302   PetscInt        numRows;
6303   const PetscInt *rows;
6304 
6305   PetscFunctionBegin;
6306   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6307   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6308   PetscValidType(mat, 1);
6309   PetscValidType(is, 2);
6310   PetscCall(ISGetLocalSize(is, &numRows));
6311   PetscCall(ISGetIndices(is, &rows));
6312   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6313   PetscCall(ISRestoreIndices(is, &rows));
6314   PetscFunctionReturn(PETSC_SUCCESS);
6315 }
6316 
6317 /*@
6318   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6319   of a set of rows of a matrix.
6320 
6321   Collective
6322 
6323   Input Parameters:
6324 + mat     - the matrix
6325 . numRows - the number of rows to zero
6326 . rows    - the global row indices
6327 . diag    - value put in the diagonal of the zeroed rows
6328 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6329 - b       - optional vector of right-hand side, that will be adjusted by provided solution entries
6330 
6331   Level: intermediate
6332 
6333   Notes:
6334   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6335 
6336   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6337 
6338   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6339   Krylov method to take advantage of the known solution on the zeroed rows.
6340 
6341   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)
6342   from the matrix.
6343 
6344   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6345   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
6346   formats this does not alter the nonzero structure.
6347 
6348   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6349   of the matrix is not changed the values are
6350   merely zeroed.
6351 
6352   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6353   formats can optionally remove the main diagonal entry from the
6354   nonzero structure as well, by passing 0.0 as the final argument).
6355 
6356   For the parallel case, all processes that share the matrix (i.e.,
6357   those in the communicator used for matrix creation) MUST call this
6358   routine, regardless of whether any rows being zeroed are owned by
6359   them.
6360 
6361   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6362   list only rows local to itself).
6363 
6364   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6365   owns that are to be zeroed. This saves a global synchronization in the implementation.
6366 
6367 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6368           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`, `MAT_KEEP_NONZERO_PATTERN`
6369 @*/
6370 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6371 {
6372   PetscFunctionBegin;
6373   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6374   PetscValidType(mat, 1);
6375   if (numRows) PetscAssertPointer(rows, 3);
6376   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6377   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6378   MatCheckPreallocated(mat, 1);
6379 
6380   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6381   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6382   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6383   PetscFunctionReturn(PETSC_SUCCESS);
6384 }
6385 
6386 /*@
6387   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6388   of a set of rows of a matrix.
6389 
6390   Collective
6391 
6392   Input Parameters:
6393 + mat  - the matrix
6394 . is   - index set of rows to remove (if `NULL` then no row is removed)
6395 . diag - value put in all diagonals of eliminated rows
6396 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6397 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6398 
6399   Level: intermediate
6400 
6401   Note:
6402   See `MatZeroRows()` for details on how this routine operates.
6403 
6404 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6405           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6406 @*/
6407 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6408 {
6409   PetscInt        numRows = 0;
6410   const PetscInt *rows    = NULL;
6411 
6412   PetscFunctionBegin;
6413   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6414   PetscValidType(mat, 1);
6415   if (is) {
6416     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6417     PetscCall(ISGetLocalSize(is, &numRows));
6418     PetscCall(ISGetIndices(is, &rows));
6419   }
6420   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6421   if (is) PetscCall(ISRestoreIndices(is, &rows));
6422   PetscFunctionReturn(PETSC_SUCCESS);
6423 }
6424 
6425 /*@
6426   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6427   of a set of rows of a matrix. These rows must be local to the process.
6428 
6429   Collective
6430 
6431   Input Parameters:
6432 + mat     - the matrix
6433 . numRows - the number of rows to remove
6434 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6435 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6436 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6437 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6438 
6439   Level: intermediate
6440 
6441   Notes:
6442   See `MatZeroRows()` for details on how this routine operates.
6443 
6444   The grid coordinates are across the entire grid, not just the local portion
6445 
6446   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6447   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6448   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6449   `DM_BOUNDARY_PERIODIC` boundary type.
6450 
6451   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
6452   a single value per point) you can skip filling those indices.
6453 
6454   Fortran Note:
6455   `idxm` and `idxn` should be declared as
6456 $     MatStencil idxm(4, m)
6457   and the values inserted using
6458 .vb
6459     idxm(MatStencil_i, 1) = i
6460     idxm(MatStencil_j, 1) = j
6461     idxm(MatStencil_k, 1) = k
6462     idxm(MatStencil_c, 1) = c
6463    etc
6464 .ve
6465 
6466 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6467           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6468 @*/
6469 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6470 {
6471   PetscInt  dim    = mat->stencil.dim;
6472   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6473   PetscInt *dims   = mat->stencil.dims + 1;
6474   PetscInt *starts = mat->stencil.starts;
6475   PetscInt *dxm    = (PetscInt *)rows;
6476   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6477 
6478   PetscFunctionBegin;
6479   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6480   PetscValidType(mat, 1);
6481   if (numRows) PetscAssertPointer(rows, 3);
6482 
6483   PetscCall(PetscMalloc1(numRows, &jdxm));
6484   for (i = 0; i < numRows; ++i) {
6485     /* Skip unused dimensions (they are ordered k, j, i, c) */
6486     for (j = 0; j < 3 - sdim; ++j) dxm++;
6487     /* Local index in X dir */
6488     tmp = *dxm++ - starts[0];
6489     /* Loop over remaining dimensions */
6490     for (j = 0; j < dim - 1; ++j) {
6491       /* If nonlocal, set index to be negative */
6492       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6493       /* Update local index */
6494       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6495     }
6496     /* Skip component slot if necessary */
6497     if (mat->stencil.noc) dxm++;
6498     /* Local row number */
6499     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6500   }
6501   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6502   PetscCall(PetscFree(jdxm));
6503   PetscFunctionReturn(PETSC_SUCCESS);
6504 }
6505 
6506 /*@
6507   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6508   of a set of rows and columns of a matrix.
6509 
6510   Collective
6511 
6512   Input Parameters:
6513 + mat     - the matrix
6514 . numRows - the number of rows/columns to remove
6515 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6516 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6517 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6518 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6519 
6520   Level: intermediate
6521 
6522   Notes:
6523   See `MatZeroRowsColumns()` for details on how this routine operates.
6524 
6525   The grid coordinates are across the entire grid, not just the local portion
6526 
6527   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6528   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6529   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6530   `DM_BOUNDARY_PERIODIC` boundary type.
6531 
6532   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
6533   a single value per point) you can skip filling those indices.
6534 
6535   Fortran Note:
6536   `idxm` and `idxn` should be declared as
6537 $     MatStencil idxm(4, m)
6538   and the values inserted using
6539 .vb
6540     idxm(MatStencil_i, 1) = i
6541     idxm(MatStencil_j, 1) = j
6542     idxm(MatStencil_k, 1) = k
6543     idxm(MatStencil_c, 1) = c
6544     etc
6545 .ve
6546 
6547 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6548           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6549 @*/
6550 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6551 {
6552   PetscInt  dim    = mat->stencil.dim;
6553   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6554   PetscInt *dims   = mat->stencil.dims + 1;
6555   PetscInt *starts = mat->stencil.starts;
6556   PetscInt *dxm    = (PetscInt *)rows;
6557   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6558 
6559   PetscFunctionBegin;
6560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6561   PetscValidType(mat, 1);
6562   if (numRows) PetscAssertPointer(rows, 3);
6563 
6564   PetscCall(PetscMalloc1(numRows, &jdxm));
6565   for (i = 0; i < numRows; ++i) {
6566     /* Skip unused dimensions (they are ordered k, j, i, c) */
6567     for (j = 0; j < 3 - sdim; ++j) dxm++;
6568     /* Local index in X dir */
6569     tmp = *dxm++ - starts[0];
6570     /* Loop over remaining dimensions */
6571     for (j = 0; j < dim - 1; ++j) {
6572       /* If nonlocal, set index to be negative */
6573       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6574       /* Update local index */
6575       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6576     }
6577     /* Skip component slot if necessary */
6578     if (mat->stencil.noc) dxm++;
6579     /* Local row number */
6580     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6581   }
6582   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6583   PetscCall(PetscFree(jdxm));
6584   PetscFunctionReturn(PETSC_SUCCESS);
6585 }
6586 
6587 /*@
6588   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6589   of a set of rows of a matrix; using local numbering of rows.
6590 
6591   Collective
6592 
6593   Input Parameters:
6594 + mat     - the matrix
6595 . numRows - the number of rows to remove
6596 . rows    - the local row indices
6597 . diag    - value put in all diagonals of eliminated rows
6598 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6599 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6600 
6601   Level: intermediate
6602 
6603   Notes:
6604   Before calling `MatZeroRowsLocal()`, the user must first set the
6605   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6606 
6607   See `MatZeroRows()` for details on how this routine operates.
6608 
6609 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6610           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6611 @*/
6612 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6613 {
6614   PetscFunctionBegin;
6615   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6616   PetscValidType(mat, 1);
6617   if (numRows) PetscAssertPointer(rows, 3);
6618   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6619   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6620   MatCheckPreallocated(mat, 1);
6621 
6622   if (mat->ops->zerorowslocal) {
6623     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6624   } else {
6625     IS              is, newis;
6626     const PetscInt *newRows;
6627 
6628     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6629     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6630     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6631     PetscCall(ISGetIndices(newis, &newRows));
6632     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6633     PetscCall(ISRestoreIndices(newis, &newRows));
6634     PetscCall(ISDestroy(&newis));
6635     PetscCall(ISDestroy(&is));
6636   }
6637   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6638   PetscFunctionReturn(PETSC_SUCCESS);
6639 }
6640 
6641 /*@
6642   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6643   of a set of rows of a matrix; using local numbering of rows.
6644 
6645   Collective
6646 
6647   Input Parameters:
6648 + mat  - the matrix
6649 . is   - index set of rows to remove
6650 . diag - value put in all diagonals of eliminated rows
6651 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6652 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6653 
6654   Level: intermediate
6655 
6656   Notes:
6657   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6658   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6659 
6660   See `MatZeroRows()` for details on how this routine operates.
6661 
6662 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6663           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6664 @*/
6665 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6666 {
6667   PetscInt        numRows;
6668   const PetscInt *rows;
6669 
6670   PetscFunctionBegin;
6671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6672   PetscValidType(mat, 1);
6673   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6674   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6675   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6676   MatCheckPreallocated(mat, 1);
6677 
6678   PetscCall(ISGetLocalSize(is, &numRows));
6679   PetscCall(ISGetIndices(is, &rows));
6680   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6681   PetscCall(ISRestoreIndices(is, &rows));
6682   PetscFunctionReturn(PETSC_SUCCESS);
6683 }
6684 
6685 /*@
6686   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6687   of a set of rows and columns of a matrix; using local numbering of rows.
6688 
6689   Collective
6690 
6691   Input Parameters:
6692 + mat     - the matrix
6693 . numRows - the number of rows to remove
6694 . rows    - the global row indices
6695 . diag    - value put in all diagonals of eliminated rows
6696 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6697 - b       - optional vector of right-hand side, that will be adjusted by provided solution
6698 
6699   Level: intermediate
6700 
6701   Notes:
6702   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6703   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6704 
6705   See `MatZeroRowsColumns()` for details on how this routine operates.
6706 
6707 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6708           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6709 @*/
6710 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6711 {
6712   IS              is, newis;
6713   const PetscInt *newRows;
6714 
6715   PetscFunctionBegin;
6716   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6717   PetscValidType(mat, 1);
6718   if (numRows) PetscAssertPointer(rows, 3);
6719   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6720   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6721   MatCheckPreallocated(mat, 1);
6722 
6723   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6724   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6725   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6726   PetscCall(ISGetIndices(newis, &newRows));
6727   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6728   PetscCall(ISRestoreIndices(newis, &newRows));
6729   PetscCall(ISDestroy(&newis));
6730   PetscCall(ISDestroy(&is));
6731   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6732   PetscFunctionReturn(PETSC_SUCCESS);
6733 }
6734 
6735 /*@
6736   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6737   of a set of rows and columns of a matrix; using local numbering of rows.
6738 
6739   Collective
6740 
6741   Input Parameters:
6742 + mat  - the matrix
6743 . is   - index set of rows to remove
6744 . diag - value put in all diagonals of eliminated rows
6745 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6746 - b    - optional vector of right-hand side, that will be adjusted by provided solution
6747 
6748   Level: intermediate
6749 
6750   Notes:
6751   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6752   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6753 
6754   See `MatZeroRowsColumns()` for details on how this routine operates.
6755 
6756 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6757           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6758 @*/
6759 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6760 {
6761   PetscInt        numRows;
6762   const PetscInt *rows;
6763 
6764   PetscFunctionBegin;
6765   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6766   PetscValidType(mat, 1);
6767   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6768   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6769   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6770   MatCheckPreallocated(mat, 1);
6771 
6772   PetscCall(ISGetLocalSize(is, &numRows));
6773   PetscCall(ISGetIndices(is, &rows));
6774   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6775   PetscCall(ISRestoreIndices(is, &rows));
6776   PetscFunctionReturn(PETSC_SUCCESS);
6777 }
6778 
6779 /*@
6780   MatGetSize - Returns the numbers of rows and columns in a matrix.
6781 
6782   Not Collective
6783 
6784   Input Parameter:
6785 . mat - the matrix
6786 
6787   Output Parameters:
6788 + m - the number of global rows
6789 - n - the number of global columns
6790 
6791   Level: beginner
6792 
6793   Note:
6794   Both output parameters can be `NULL` on input.
6795 
6796 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6797 @*/
6798 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6799 {
6800   PetscFunctionBegin;
6801   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6802   if (m) *m = mat->rmap->N;
6803   if (n) *n = mat->cmap->N;
6804   PetscFunctionReturn(PETSC_SUCCESS);
6805 }
6806 
6807 /*@
6808   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6809   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6810 
6811   Not Collective
6812 
6813   Input Parameter:
6814 . mat - the matrix
6815 
6816   Output Parameters:
6817 + m - the number of local rows, use `NULL` to not obtain this value
6818 - n - the number of local columns, use `NULL` to not obtain this value
6819 
6820   Level: beginner
6821 
6822 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6823 @*/
6824 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6825 {
6826   PetscFunctionBegin;
6827   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6828   if (m) PetscAssertPointer(m, 2);
6829   if (n) PetscAssertPointer(n, 3);
6830   if (m) *m = mat->rmap->n;
6831   if (n) *n = mat->cmap->n;
6832   PetscFunctionReturn(PETSC_SUCCESS);
6833 }
6834 
6835 /*@
6836   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6837   vector one multiplies this matrix by that are owned by this processor.
6838 
6839   Not Collective, unless matrix has not been allocated, then collective
6840 
6841   Input Parameter:
6842 . mat - the matrix
6843 
6844   Output Parameters:
6845 + m - the global index of the first local column, use `NULL` to not obtain this value
6846 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6847 
6848   Level: developer
6849 
6850   Notes:
6851   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6852 
6853   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6854   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6855 
6856   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6857   the local values in the matrix.
6858 
6859   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6860   Layouts](sec_matlayout) for details on matrix layouts.
6861 
6862 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6863           `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6864 @*/
6865 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6866 {
6867   PetscFunctionBegin;
6868   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6869   PetscValidType(mat, 1);
6870   if (m) PetscAssertPointer(m, 2);
6871   if (n) PetscAssertPointer(n, 3);
6872   MatCheckPreallocated(mat, 1);
6873   if (m) *m = mat->cmap->rstart;
6874   if (n) *n = mat->cmap->rend;
6875   PetscFunctionReturn(PETSC_SUCCESS);
6876 }
6877 
6878 /*@
6879   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6880   this MPI process.
6881 
6882   Not Collective
6883 
6884   Input Parameter:
6885 . mat - the matrix
6886 
6887   Output Parameters:
6888 + m - the global index of the first local row, use `NULL` to not obtain this value
6889 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6890 
6891   Level: beginner
6892 
6893   Notes:
6894   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6895 
6896   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6897   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6898 
6899   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6900   the local values in the matrix.
6901 
6902   The high argument is one more than the last element stored locally.
6903 
6904   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6905   would contain the result of a matrix vector product with this matrix. See [Matrix
6906   Layouts](sec_matlayout) for details on matrix layouts.
6907 
6908 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`,
6909           `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`, `DMDAGetGhostCorners()`, `DM`
6910 @*/
6911 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6912 {
6913   PetscFunctionBegin;
6914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6915   PetscValidType(mat, 1);
6916   if (m) PetscAssertPointer(m, 2);
6917   if (n) PetscAssertPointer(n, 3);
6918   MatCheckPreallocated(mat, 1);
6919   if (m) *m = mat->rmap->rstart;
6920   if (n) *n = mat->rmap->rend;
6921   PetscFunctionReturn(PETSC_SUCCESS);
6922 }
6923 
6924 /*@C
6925   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6926   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6927 
6928   Not Collective, unless matrix has not been allocated
6929 
6930   Input Parameter:
6931 . mat - the matrix
6932 
6933   Output Parameter:
6934 . ranges - start of each processors portion plus one more than the total length at the end, of length `size` + 1
6935            where `size` is the number of MPI processes used by `mat`
6936 
6937   Level: beginner
6938 
6939   Notes:
6940   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6941 
6942   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6943   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6944 
6945   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6946   the local values in the matrix.
6947 
6948   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6949   would contain the result of a matrix vector product with this matrix. See [Matrix
6950   Layouts](sec_matlayout) for details on matrix layouts.
6951 
6952 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`,
6953           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `MatSetSizes()`, `MatCreateAIJ()`,
6954           `DMDAGetGhostCorners()`, `DM`
6955 @*/
6956 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt *ranges[])
6957 {
6958   PetscFunctionBegin;
6959   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6960   PetscValidType(mat, 1);
6961   MatCheckPreallocated(mat, 1);
6962   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6963   PetscFunctionReturn(PETSC_SUCCESS);
6964 }
6965 
6966 /*@C
6967   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6968   vector one multiplies this vector by that are owned by each processor.
6969 
6970   Not Collective, unless matrix has not been allocated
6971 
6972   Input Parameter:
6973 . mat - the matrix
6974 
6975   Output Parameter:
6976 . ranges - start of each processors portion plus one more than the total length at the end
6977 
6978   Level: beginner
6979 
6980   Notes:
6981   If the `Mat` was obtained from a `DM` with `DMCreateMatrix()`, then the range values are determined by the specific `DM`.
6982 
6983   If the `Mat` was created directly the range values are determined by the local size passed to `MatSetSizes()` or `MatCreateAIJ()`.
6984   If `PETSC_DECIDE` was passed as the local size, then the vector uses default values for the range using `PetscSplitOwnership()`.
6985 
6986   For certain `DM`, such as `DMDA`, it is better to use `DM` specific routines, such as `DMDAGetGhostCorners()`, to determine
6987   the local values in the matrix.
6988 
6989   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6990   Layouts](sec_matlayout) for details on matrix layouts.
6991 
6992 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`,
6993           `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`, `PetscLayout`, `MatSetSizes()`, `MatCreateAIJ()`,
6994           `DMDAGetGhostCorners()`, `DM`
6995 @*/
6996 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt *ranges[])
6997 {
6998   PetscFunctionBegin;
6999   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7000   PetscValidType(mat, 1);
7001   MatCheckPreallocated(mat, 1);
7002   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
7003   PetscFunctionReturn(PETSC_SUCCESS);
7004 }
7005 
7006 /*@
7007   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
7008 
7009   Not Collective
7010 
7011   Input Parameter:
7012 . A - matrix
7013 
7014   Output Parameters:
7015 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
7016 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
7017 
7018   Level: intermediate
7019 
7020   Note:
7021   You should call `ISDestroy()` on the returned `IS`
7022 
7023   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
7024   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
7025   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
7026   details on matrix layouts.
7027 
7028 .seealso: [](ch_matrices), `IS`, `Mat`, `MatGetOwnershipRanges()`, `MatSetValues()`, `MATELEMENTAL`, `MATSCALAPACK`
7029 @*/
7030 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
7031 {
7032   PetscErrorCode (*f)(Mat, IS *, IS *);
7033 
7034   PetscFunctionBegin;
7035   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
7036   PetscValidType(A, 1);
7037   MatCheckPreallocated(A, 1);
7038   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
7039   if (f) {
7040     PetscCall((*f)(A, rows, cols));
7041   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
7042     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
7043     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
7044   }
7045   PetscFunctionReturn(PETSC_SUCCESS);
7046 }
7047 
7048 /*@
7049   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
7050   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
7051   to complete the factorization.
7052 
7053   Collective
7054 
7055   Input Parameters:
7056 + fact - the factorized matrix obtained with `MatGetFactor()`
7057 . mat  - the matrix
7058 . row  - row permutation
7059 . col  - column permutation
7060 - info - structure containing
7061 .vb
7062       levels - number of levels of fill.
7063       expected fill - as ratio of original fill.
7064       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
7065                 missing diagonal entries)
7066 .ve
7067 
7068   Level: developer
7069 
7070   Notes:
7071   See [Matrix Factorization](sec_matfactor) for additional information.
7072 
7073   Most users should employ the `KSP` interface for linear solvers
7074   instead of working directly with matrix algebra routines such as this.
7075   See, e.g., `KSPCreate()`.
7076 
7077   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
7078 
7079   Developer Note:
7080   The Fortran interface is not autogenerated as the
7081   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7082 
7083 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
7084           `MatGetOrdering()`, `MatFactorInfo`
7085 @*/
7086 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
7087 {
7088   PetscFunctionBegin;
7089   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7090   PetscValidType(mat, 2);
7091   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
7092   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
7093   PetscAssertPointer(info, 5);
7094   PetscAssertPointer(fact, 1);
7095   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
7096   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7097   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7098   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7099   MatCheckPreallocated(mat, 2);
7100 
7101   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
7102   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
7103   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
7104   PetscFunctionReturn(PETSC_SUCCESS);
7105 }
7106 
7107 /*@
7108   MatICCFactorSymbolic - Performs symbolic incomplete
7109   Cholesky factorization for a symmetric matrix.  Use
7110   `MatCholeskyFactorNumeric()` to complete the factorization.
7111 
7112   Collective
7113 
7114   Input Parameters:
7115 + fact - the factorized matrix obtained with `MatGetFactor()`
7116 . mat  - the matrix to be factored
7117 . perm - row and column permutation
7118 - info - structure containing
7119 .vb
7120       levels - number of levels of fill.
7121       expected fill - as ratio of original fill.
7122 .ve
7123 
7124   Level: developer
7125 
7126   Notes:
7127   Most users should employ the `KSP` interface for linear solvers
7128   instead of working directly with matrix algebra routines such as this.
7129   See, e.g., `KSPCreate()`.
7130 
7131   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7132 
7133   Developer Note:
7134   The Fortran interface is not autogenerated as the
7135   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7136 
7137 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7138 @*/
7139 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7140 {
7141   PetscFunctionBegin;
7142   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7143   PetscValidType(mat, 2);
7144   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7145   PetscAssertPointer(info, 4);
7146   PetscAssertPointer(fact, 1);
7147   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7148   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7149   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7150   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7151   MatCheckPreallocated(mat, 2);
7152 
7153   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7154   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7155   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7156   PetscFunctionReturn(PETSC_SUCCESS);
7157 }
7158 
7159 /*@C
7160   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7161   points to an array of valid matrices, they may be reused to store the new
7162   submatrices.
7163 
7164   Collective
7165 
7166   Input Parameters:
7167 + mat   - the matrix
7168 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7169 . irow  - index set of rows to extract
7170 . icol  - index set of columns to extract
7171 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7172 
7173   Output Parameter:
7174 . submat - the array of submatrices
7175 
7176   Level: advanced
7177 
7178   Notes:
7179   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7180   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7181   to extract a parallel submatrix.
7182 
7183   Some matrix types place restrictions on the row and column
7184   indices, such as that they be sorted or that they be equal to each other.
7185 
7186   The index sets may not have duplicate entries.
7187 
7188   When extracting submatrices from a parallel matrix, each processor can
7189   form a different submatrix by setting the rows and columns of its
7190   individual index sets according to the local submatrix desired.
7191 
7192   When finished using the submatrices, the user should destroy
7193   them with `MatDestroySubMatrices()`.
7194 
7195   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7196   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7197 
7198   This routine creates the matrices in submat; you should NOT create them before
7199   calling it. It also allocates the array of matrix pointers submat.
7200 
7201   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7202   request one row/column in a block, they must request all rows/columns that are in
7203   that block. For example, if the block size is 2 you cannot request just row 0 and
7204   column 0.
7205 
7206   Fortran Note:
7207   One must pass in as `submat` a `Mat` array of size at least `n`+1.
7208 
7209 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7210 @*/
7211 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7212 {
7213   PetscInt  i;
7214   PetscBool eq;
7215 
7216   PetscFunctionBegin;
7217   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7218   PetscValidType(mat, 1);
7219   if (n) {
7220     PetscAssertPointer(irow, 3);
7221     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7222     PetscAssertPointer(icol, 4);
7223     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7224   }
7225   PetscAssertPointer(submat, 6);
7226   if (n && scall == MAT_REUSE_MATRIX) {
7227     PetscAssertPointer(*submat, 6);
7228     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7229   }
7230   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7231   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7232   MatCheckPreallocated(mat, 1);
7233   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7234   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7235   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7236   for (i = 0; i < n; i++) {
7237     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7238     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7239     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7240 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7241     if (mat->boundtocpu && mat->bindingpropagates) {
7242       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7243       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7244     }
7245 #endif
7246   }
7247   PetscFunctionReturn(PETSC_SUCCESS);
7248 }
7249 
7250 /*@C
7251   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7252 
7253   Collective
7254 
7255   Input Parameters:
7256 + mat   - the matrix
7257 . n     - the number of submatrixes to be extracted
7258 . irow  - index set of rows to extract
7259 . icol  - index set of columns to extract
7260 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7261 
7262   Output Parameter:
7263 . submat - the array of submatrices
7264 
7265   Level: advanced
7266 
7267   Note:
7268   This is used by `PCGASM`
7269 
7270 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7271 @*/
7272 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7273 {
7274   PetscInt  i;
7275   PetscBool eq;
7276 
7277   PetscFunctionBegin;
7278   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7279   PetscValidType(mat, 1);
7280   if (n) {
7281     PetscAssertPointer(irow, 3);
7282     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7283     PetscAssertPointer(icol, 4);
7284     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7285   }
7286   PetscAssertPointer(submat, 6);
7287   if (n && scall == MAT_REUSE_MATRIX) {
7288     PetscAssertPointer(*submat, 6);
7289     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7290   }
7291   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7292   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7293   MatCheckPreallocated(mat, 1);
7294 
7295   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7296   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7297   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7298   for (i = 0; i < n; i++) {
7299     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7300     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7301   }
7302   PetscFunctionReturn(PETSC_SUCCESS);
7303 }
7304 
7305 /*@C
7306   MatDestroyMatrices - Destroys an array of matrices.
7307 
7308   Collective
7309 
7310   Input Parameters:
7311 + n   - the number of local matrices
7312 - mat - the matrices (this is a pointer to the array of matrices)
7313 
7314   Level: advanced
7315 
7316   Notes:
7317   Frees not only the matrices, but also the array that contains the matrices
7318 
7319   For matrices obtained with  `MatCreateSubMatrices()` use `MatDestroySubMatrices()`
7320 
7321   Fortran Note:
7322   Does not free the `mat` array.
7323 
7324 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroySubMatrices()`
7325 @*/
7326 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7327 {
7328   PetscInt i;
7329 
7330   PetscFunctionBegin;
7331   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7332   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7333   PetscAssertPointer(mat, 2);
7334 
7335   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7336 
7337   /* memory is allocated even if n = 0 */
7338   PetscCall(PetscFree(*mat));
7339   PetscFunctionReturn(PETSC_SUCCESS);
7340 }
7341 
7342 /*@C
7343   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7344 
7345   Collective
7346 
7347   Input Parameters:
7348 + n   - the number of local matrices
7349 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7350                        sequence of `MatCreateSubMatrices()`)
7351 
7352   Level: advanced
7353 
7354   Note:
7355   Frees not only the matrices, but also the array that contains the matrices
7356 
7357   Fortran Note:
7358   Does not free the `mat` array.
7359 
7360 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7361 @*/
7362 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7363 {
7364   Mat mat0;
7365 
7366   PetscFunctionBegin;
7367   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7368   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7369   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7370   PetscAssertPointer(mat, 2);
7371 
7372   mat0 = (*mat)[0];
7373   if (mat0 && mat0->ops->destroysubmatrices) {
7374     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7375   } else {
7376     PetscCall(MatDestroyMatrices(n, mat));
7377   }
7378   PetscFunctionReturn(PETSC_SUCCESS);
7379 }
7380 
7381 /*@
7382   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7383 
7384   Collective
7385 
7386   Input Parameter:
7387 . mat - the matrix
7388 
7389   Output Parameter:
7390 . matstruct - the sequential matrix with the nonzero structure of `mat`
7391 
7392   Level: developer
7393 
7394 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7395 @*/
7396 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7397 {
7398   PetscFunctionBegin;
7399   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7400   PetscAssertPointer(matstruct, 2);
7401 
7402   PetscValidType(mat, 1);
7403   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7404   MatCheckPreallocated(mat, 1);
7405 
7406   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7407   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7408   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7409   PetscFunctionReturn(PETSC_SUCCESS);
7410 }
7411 
7412 /*@C
7413   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7414 
7415   Collective
7416 
7417   Input Parameter:
7418 . mat - the matrix
7419 
7420   Level: advanced
7421 
7422   Note:
7423   This is not needed, one can just call `MatDestroy()`
7424 
7425 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7426 @*/
7427 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7428 {
7429   PetscFunctionBegin;
7430   PetscAssertPointer(mat, 1);
7431   PetscCall(MatDestroy(mat));
7432   PetscFunctionReturn(PETSC_SUCCESS);
7433 }
7434 
7435 /*@
7436   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7437   replaces the index sets by larger ones that represent submatrices with
7438   additional overlap.
7439 
7440   Collective
7441 
7442   Input Parameters:
7443 + mat - the matrix
7444 . n   - the number of index sets
7445 . is  - the array of index sets (these index sets will changed during the call)
7446 - ov  - the additional overlap requested
7447 
7448   Options Database Key:
7449 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7450 
7451   Level: developer
7452 
7453   Note:
7454   The computed overlap preserves the matrix block sizes when the blocks are square.
7455   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7456   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7457 
7458 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7459 @*/
7460 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7461 {
7462   PetscInt i, bs, cbs;
7463 
7464   PetscFunctionBegin;
7465   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7466   PetscValidType(mat, 1);
7467   PetscValidLogicalCollectiveInt(mat, n, 2);
7468   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7469   if (n) {
7470     PetscAssertPointer(is, 3);
7471     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7472   }
7473   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7474   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7475   MatCheckPreallocated(mat, 1);
7476 
7477   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7478   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7479   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7480   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7481   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7482   if (bs == cbs) {
7483     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7484   }
7485   PetscFunctionReturn(PETSC_SUCCESS);
7486 }
7487 
7488 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7489 
7490 /*@
7491   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7492   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7493   additional overlap.
7494 
7495   Collective
7496 
7497   Input Parameters:
7498 + mat - the matrix
7499 . n   - the number of index sets
7500 . is  - the array of index sets (these index sets will changed during the call)
7501 - ov  - the additional overlap requested
7502 
7503   `   Options Database Key:
7504 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7505 
7506   Level: developer
7507 
7508 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7509 @*/
7510 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7511 {
7512   PetscInt i;
7513 
7514   PetscFunctionBegin;
7515   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7516   PetscValidType(mat, 1);
7517   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7518   if (n) {
7519     PetscAssertPointer(is, 3);
7520     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7521   }
7522   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7523   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7524   MatCheckPreallocated(mat, 1);
7525   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7526   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7527   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7528   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7529   PetscFunctionReturn(PETSC_SUCCESS);
7530 }
7531 
7532 /*@
7533   MatGetBlockSize - Returns the matrix block size.
7534 
7535   Not Collective
7536 
7537   Input Parameter:
7538 . mat - the matrix
7539 
7540   Output Parameter:
7541 . bs - block size
7542 
7543   Level: intermediate
7544 
7545   Notes:
7546   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7547 
7548   If the block size has not been set yet this routine returns 1.
7549 
7550 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7551 @*/
7552 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7553 {
7554   PetscFunctionBegin;
7555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7556   PetscAssertPointer(bs, 2);
7557   *bs = PetscAbs(mat->rmap->bs);
7558   PetscFunctionReturn(PETSC_SUCCESS);
7559 }
7560 
7561 /*@
7562   MatGetBlockSizes - Returns the matrix block row and column sizes.
7563 
7564   Not Collective
7565 
7566   Input Parameter:
7567 . mat - the matrix
7568 
7569   Output Parameters:
7570 + rbs - row block size
7571 - cbs - column block size
7572 
7573   Level: intermediate
7574 
7575   Notes:
7576   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7577   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7578 
7579   If a block size has not been set yet this routine returns 1.
7580 
7581 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7582 @*/
7583 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7584 {
7585   PetscFunctionBegin;
7586   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7587   if (rbs) PetscAssertPointer(rbs, 2);
7588   if (cbs) PetscAssertPointer(cbs, 3);
7589   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7590   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7591   PetscFunctionReturn(PETSC_SUCCESS);
7592 }
7593 
7594 /*@
7595   MatSetBlockSize - Sets the matrix block size.
7596 
7597   Logically Collective
7598 
7599   Input Parameters:
7600 + mat - the matrix
7601 - bs  - block size
7602 
7603   Level: intermediate
7604 
7605   Notes:
7606   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7607   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7608 
7609   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7610   is compatible with the matrix local sizes.
7611 
7612 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7613 @*/
7614 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7615 {
7616   PetscFunctionBegin;
7617   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7618   PetscValidLogicalCollectiveInt(mat, bs, 2);
7619   PetscCall(MatSetBlockSizes(mat, bs, bs));
7620   PetscFunctionReturn(PETSC_SUCCESS);
7621 }
7622 
7623 typedef struct {
7624   PetscInt         n;
7625   IS              *is;
7626   Mat             *mat;
7627   PetscObjectState nonzerostate;
7628   Mat              C;
7629 } EnvelopeData;
7630 
7631 static PetscErrorCode EnvelopeDataDestroy(void *ptr)
7632 {
7633   EnvelopeData *edata = (EnvelopeData *)ptr;
7634 
7635   PetscFunctionBegin;
7636   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7637   PetscCall(PetscFree(edata->is));
7638   PetscCall(PetscFree(edata));
7639   PetscFunctionReturn(PETSC_SUCCESS);
7640 }
7641 
7642 /*@
7643   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7644   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7645 
7646   Collective
7647 
7648   Input Parameter:
7649 . mat - the matrix
7650 
7651   Level: intermediate
7652 
7653   Notes:
7654   There can be zeros within the blocks
7655 
7656   The blocks can overlap between processes, including laying on more than two processes
7657 
7658 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7659 @*/
7660 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7661 {
7662   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7663   PetscInt          *diag, *odiag, sc;
7664   VecScatter         scatter;
7665   PetscScalar       *seqv;
7666   const PetscScalar *parv;
7667   const PetscInt    *ia, *ja;
7668   PetscBool          set, flag, done;
7669   Mat                AA = mat, A;
7670   MPI_Comm           comm;
7671   PetscMPIInt        rank, size, tag;
7672   MPI_Status         status;
7673   PetscContainer     container;
7674   EnvelopeData      *edata;
7675   Vec                seq, par;
7676   IS                 isglobal;
7677 
7678   PetscFunctionBegin;
7679   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7680   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7681   if (!set || !flag) {
7682     /* TODO: only needs nonzero structure of transpose */
7683     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7684     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7685   }
7686   PetscCall(MatAIJGetLocalMat(AA, &A));
7687   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7688   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7689 
7690   PetscCall(MatGetLocalSize(mat, &n, NULL));
7691   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7692   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7693   PetscCallMPI(MPI_Comm_size(comm, &size));
7694   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7695 
7696   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7697 
7698   if (rank > 0) {
7699     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7700     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7701   }
7702   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7703   for (i = 0; i < n; i++) {
7704     env = PetscMax(env, ja[ia[i + 1] - 1]);
7705     II  = rstart + i;
7706     if (env == II) {
7707       starts[lblocks]  = tbs;
7708       sizes[lblocks++] = 1 + II - tbs;
7709       tbs              = 1 + II;
7710     }
7711   }
7712   if (rank < size - 1) {
7713     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7714     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7715   }
7716 
7717   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7718   if (!set || !flag) PetscCall(MatDestroy(&AA));
7719   PetscCall(MatDestroy(&A));
7720 
7721   PetscCall(PetscNew(&edata));
7722   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7723   edata->n = lblocks;
7724   /* create IS needed for extracting blocks from the original matrix */
7725   PetscCall(PetscMalloc1(lblocks, &edata->is));
7726   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7727 
7728   /* Create the resulting inverse matrix structure with preallocation information */
7729   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7730   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7731   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7732   PetscCall(MatSetType(edata->C, MATAIJ));
7733 
7734   /* Communicate the start and end of each row, from each block to the correct rank */
7735   /* TODO: Use PetscSF instead of VecScatter */
7736   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7737   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7738   PetscCall(VecGetArrayWrite(seq, &seqv));
7739   for (PetscInt i = 0; i < lblocks; i++) {
7740     for (PetscInt j = 0; j < sizes[i]; j++) {
7741       seqv[cnt]     = starts[i];
7742       seqv[cnt + 1] = starts[i] + sizes[i];
7743       cnt += 2;
7744     }
7745   }
7746   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7747   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7748   sc -= cnt;
7749   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7750   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7751   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7752   PetscCall(ISDestroy(&isglobal));
7753   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7754   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7755   PetscCall(VecScatterDestroy(&scatter));
7756   PetscCall(VecDestroy(&seq));
7757   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7758   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7759   PetscCall(VecGetArrayRead(par, &parv));
7760   cnt = 0;
7761   PetscCall(MatGetSize(mat, NULL, &n));
7762   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7763     PetscInt start, end, d = 0, od = 0;
7764 
7765     start = (PetscInt)PetscRealPart(parv[cnt]);
7766     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7767     cnt += 2;
7768 
7769     if (start < cstart) {
7770       od += cstart - start + n - cend;
7771       d += cend - cstart;
7772     } else if (start < cend) {
7773       od += n - cend;
7774       d += cend - start;
7775     } else od += n - start;
7776     if (end <= cstart) {
7777       od -= cstart - end + n - cend;
7778       d -= cend - cstart;
7779     } else if (end < cend) {
7780       od -= n - cend;
7781       d -= cend - end;
7782     } else od -= n - end;
7783 
7784     odiag[i] = od;
7785     diag[i]  = d;
7786   }
7787   PetscCall(VecRestoreArrayRead(par, &parv));
7788   PetscCall(VecDestroy(&par));
7789   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7790   PetscCall(PetscFree2(diag, odiag));
7791   PetscCall(PetscFree2(sizes, starts));
7792 
7793   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7794   PetscCall(PetscContainerSetPointer(container, edata));
7795   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7796   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7797   PetscCall(PetscObjectDereference((PetscObject)container));
7798   PetscFunctionReturn(PETSC_SUCCESS);
7799 }
7800 
7801 /*@
7802   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7803 
7804   Collective
7805 
7806   Input Parameters:
7807 + A     - the matrix
7808 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7809 
7810   Output Parameter:
7811 . C - matrix with inverted block diagonal of `A`
7812 
7813   Level: advanced
7814 
7815   Note:
7816   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7817 
7818 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7819 @*/
7820 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7821 {
7822   PetscContainer   container;
7823   EnvelopeData    *edata;
7824   PetscObjectState nonzerostate;
7825 
7826   PetscFunctionBegin;
7827   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7828   if (!container) {
7829     PetscCall(MatComputeVariableBlockEnvelope(A));
7830     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7831   }
7832   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7833   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7834   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7835   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7836 
7837   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7838   *C = edata->C;
7839 
7840   for (PetscInt i = 0; i < edata->n; i++) {
7841     Mat          D;
7842     PetscScalar *dvalues;
7843 
7844     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7845     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7846     PetscCall(MatSeqDenseInvert(D));
7847     PetscCall(MatDenseGetArray(D, &dvalues));
7848     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7849     PetscCall(MatDestroy(&D));
7850   }
7851   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7852   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7853   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7854   PetscFunctionReturn(PETSC_SUCCESS);
7855 }
7856 
7857 /*@
7858   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7859 
7860   Not Collective
7861 
7862   Input Parameters:
7863 + mat     - the matrix
7864 . nblocks - the number of blocks on this process, each block can only exist on a single process
7865 - bsizes  - the block sizes
7866 
7867   Level: intermediate
7868 
7869   Notes:
7870   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7871 
7872   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.
7873 
7874 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7875           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7876 @*/
7877 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, const PetscInt bsizes[])
7878 {
7879   PetscInt ncnt = 0, nlocal;
7880 
7881   PetscFunctionBegin;
7882   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7883   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7884   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);
7885   for (PetscInt i = 0; i < nblocks; i++) ncnt += bsizes[i];
7886   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);
7887   PetscCall(PetscFree(mat->bsizes));
7888   mat->nblocks = nblocks;
7889   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7890   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7891   PetscFunctionReturn(PETSC_SUCCESS);
7892 }
7893 
7894 /*@C
7895   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7896 
7897   Not Collective; No Fortran Support
7898 
7899   Input Parameter:
7900 . mat - the matrix
7901 
7902   Output Parameters:
7903 + nblocks - the number of blocks on this process
7904 - bsizes  - the block sizes
7905 
7906   Level: intermediate
7907 
7908 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7909 @*/
7910 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt *bsizes[])
7911 {
7912   PetscFunctionBegin;
7913   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7914   if (nblocks) *nblocks = mat->nblocks;
7915   if (bsizes) *bsizes = mat->bsizes;
7916   PetscFunctionReturn(PETSC_SUCCESS);
7917 }
7918 
7919 /*@
7920   MatSetBlockSizes - Sets the matrix block row and column sizes.
7921 
7922   Logically Collective
7923 
7924   Input Parameters:
7925 + mat - the matrix
7926 . rbs - row block size
7927 - cbs - column block size
7928 
7929   Level: intermediate
7930 
7931   Notes:
7932   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7933   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7934   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7935 
7936   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7937   are compatible with the matrix local sizes.
7938 
7939   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7940 
7941 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7942 @*/
7943 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7944 {
7945   PetscFunctionBegin;
7946   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7947   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7948   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7949   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7950   if (mat->rmap->refcnt) {
7951     ISLocalToGlobalMapping l2g  = NULL;
7952     PetscLayout            nmap = NULL;
7953 
7954     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7955     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7956     PetscCall(PetscLayoutDestroy(&mat->rmap));
7957     mat->rmap          = nmap;
7958     mat->rmap->mapping = l2g;
7959   }
7960   if (mat->cmap->refcnt) {
7961     ISLocalToGlobalMapping l2g  = NULL;
7962     PetscLayout            nmap = NULL;
7963 
7964     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7965     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7966     PetscCall(PetscLayoutDestroy(&mat->cmap));
7967     mat->cmap          = nmap;
7968     mat->cmap->mapping = l2g;
7969   }
7970   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7971   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7972   PetscFunctionReturn(PETSC_SUCCESS);
7973 }
7974 
7975 /*@
7976   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7977 
7978   Logically Collective
7979 
7980   Input Parameters:
7981 + mat     - the matrix
7982 . fromRow - matrix from which to copy row block size
7983 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7984 
7985   Level: developer
7986 
7987 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7988 @*/
7989 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7990 {
7991   PetscFunctionBegin;
7992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7993   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7994   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7995   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7996   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7997   PetscFunctionReturn(PETSC_SUCCESS);
7998 }
7999 
8000 /*@
8001   MatResidual - Default routine to calculate the residual r = b - Ax
8002 
8003   Collective
8004 
8005   Input Parameters:
8006 + mat - the matrix
8007 . b   - the right-hand-side
8008 - x   - the approximate solution
8009 
8010   Output Parameter:
8011 . r - location to store the residual
8012 
8013   Level: developer
8014 
8015 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
8016 @*/
8017 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
8018 {
8019   PetscFunctionBegin;
8020   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8021   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
8022   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
8023   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
8024   PetscValidType(mat, 1);
8025   MatCheckPreallocated(mat, 1);
8026   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
8027   if (!mat->ops->residual) {
8028     PetscCall(MatMult(mat, x, r));
8029     PetscCall(VecAYPX(r, -1.0, b));
8030   } else {
8031     PetscUseTypeMethod(mat, residual, b, x, r);
8032   }
8033   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
8034   PetscFunctionReturn(PETSC_SUCCESS);
8035 }
8036 
8037 /*MC
8038     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
8039 
8040     Synopsis:
8041     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8042 
8043     Not Collective
8044 
8045     Input Parameters:
8046 +   A - the matrix
8047 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8048 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8049 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8050                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8051                  always used.
8052 
8053     Output Parameters:
8054 +   n - number of local rows in the (possibly compressed) matrix
8055 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8056 .   ja - the column indices
8057 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8058            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8059 
8060     Level: developer
8061 
8062     Note:
8063     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
8064 
8065 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
8066 M*/
8067 
8068 /*MC
8069     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
8070 
8071     Synopsis:
8072     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
8073 
8074     Not Collective
8075 
8076     Input Parameters:
8077 +   A - the  matrix
8078 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
8079 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8080     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8081                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8082                  always used.
8083 .   n - number of local rows in the (possibly compressed) matrix
8084 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
8085 .   ja - the column indices
8086 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8087            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8088 
8089     Level: developer
8090 
8091 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
8092 M*/
8093 
8094 /*@C
8095   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
8096 
8097   Collective
8098 
8099   Input Parameters:
8100 + mat             - the matrix
8101 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
8102 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8103 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
8104                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8105                  always used.
8106 
8107   Output Parameters:
8108 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8109 . 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
8110 . ja   - the column indices, use `NULL` if not needed
8111 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8112            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8113 
8114   Level: developer
8115 
8116   Notes:
8117   You CANNOT change any of the ia[] or ja[] values.
8118 
8119   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8120 
8121   Fortran Notes:
8122   Use
8123 .vb
8124     PetscInt, pointer :: ia(:),ja(:)
8125     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8126     ! Access the ith and jth entries via ia(i) and ja(j)
8127 .ve
8128 
8129   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8130 
8131 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8132 @*/
8133 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8134 {
8135   PetscFunctionBegin;
8136   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8137   PetscValidType(mat, 1);
8138   if (n) PetscAssertPointer(n, 5);
8139   if (ia) PetscAssertPointer(ia, 6);
8140   if (ja) PetscAssertPointer(ja, 7);
8141   if (done) PetscAssertPointer(done, 8);
8142   MatCheckPreallocated(mat, 1);
8143   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8144   else {
8145     if (done) *done = PETSC_TRUE;
8146     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8147     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8148     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8149   }
8150   PetscFunctionReturn(PETSC_SUCCESS);
8151 }
8152 
8153 /*@C
8154   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8155 
8156   Collective
8157 
8158   Input Parameters:
8159 + mat             - the matrix
8160 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8161 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8162                 symmetrized
8163 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8164                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8165                  always used.
8166 . n               - number of columns in the (possibly compressed) matrix
8167 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8168 - ja              - the row indices
8169 
8170   Output Parameter:
8171 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8172 
8173   Level: developer
8174 
8175 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8176 @*/
8177 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8178 {
8179   PetscFunctionBegin;
8180   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8181   PetscValidType(mat, 1);
8182   PetscAssertPointer(n, 5);
8183   if (ia) PetscAssertPointer(ia, 6);
8184   if (ja) PetscAssertPointer(ja, 7);
8185   PetscAssertPointer(done, 8);
8186   MatCheckPreallocated(mat, 1);
8187   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8188   else {
8189     *done = PETSC_TRUE;
8190     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8191   }
8192   PetscFunctionReturn(PETSC_SUCCESS);
8193 }
8194 
8195 /*@C
8196   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8197 
8198   Collective
8199 
8200   Input Parameters:
8201 + mat             - the matrix
8202 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8203 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8204 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8205                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8206                     always used.
8207 . n               - size of (possibly compressed) matrix
8208 . ia              - the row pointers
8209 - ja              - the column indices
8210 
8211   Output Parameter:
8212 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8213 
8214   Level: developer
8215 
8216   Note:
8217   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8218   us of the array after it has been restored. If you pass `NULL`, it will
8219   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8220 
8221   Fortran Note:
8222   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8223 
8224 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8225 @*/
8226 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8227 {
8228   PetscFunctionBegin;
8229   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8230   PetscValidType(mat, 1);
8231   if (ia) PetscAssertPointer(ia, 6);
8232   if (ja) PetscAssertPointer(ja, 7);
8233   if (done) PetscAssertPointer(done, 8);
8234   MatCheckPreallocated(mat, 1);
8235 
8236   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8237   else {
8238     if (done) *done = PETSC_TRUE;
8239     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8240     if (n) *n = 0;
8241     if (ia) *ia = NULL;
8242     if (ja) *ja = NULL;
8243   }
8244   PetscFunctionReturn(PETSC_SUCCESS);
8245 }
8246 
8247 /*@C
8248   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8249 
8250   Collective
8251 
8252   Input Parameters:
8253 + mat             - the matrix
8254 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8255 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8256 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8257                     inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8258                     always used.
8259 
8260   Output Parameters:
8261 + n    - size of (possibly compressed) matrix
8262 . ia   - the column pointers
8263 . ja   - the row indices
8264 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8265 
8266   Level: developer
8267 
8268 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8269 @*/
8270 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8271 {
8272   PetscFunctionBegin;
8273   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8274   PetscValidType(mat, 1);
8275   if (ia) PetscAssertPointer(ia, 6);
8276   if (ja) PetscAssertPointer(ja, 7);
8277   PetscAssertPointer(done, 8);
8278   MatCheckPreallocated(mat, 1);
8279 
8280   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8281   else {
8282     *done = PETSC_TRUE;
8283     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8284     if (n) *n = 0;
8285     if (ia) *ia = NULL;
8286     if (ja) *ja = NULL;
8287   }
8288   PetscFunctionReturn(PETSC_SUCCESS);
8289 }
8290 
8291 /*@
8292   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8293   `MatGetColumnIJ()`.
8294 
8295   Collective
8296 
8297   Input Parameters:
8298 + mat        - the matrix
8299 . ncolors    - maximum color value
8300 . n          - number of entries in colorarray
8301 - colorarray - array indicating color for each column
8302 
8303   Output Parameter:
8304 . iscoloring - coloring generated using colorarray information
8305 
8306   Level: developer
8307 
8308 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8309 @*/
8310 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8311 {
8312   PetscFunctionBegin;
8313   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8314   PetscValidType(mat, 1);
8315   PetscAssertPointer(colorarray, 4);
8316   PetscAssertPointer(iscoloring, 5);
8317   MatCheckPreallocated(mat, 1);
8318 
8319   if (!mat->ops->coloringpatch) {
8320     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8321   } else {
8322     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8323   }
8324   PetscFunctionReturn(PETSC_SUCCESS);
8325 }
8326 
8327 /*@
8328   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8329 
8330   Logically Collective
8331 
8332   Input Parameter:
8333 . mat - the factored matrix to be reset
8334 
8335   Level: developer
8336 
8337   Notes:
8338   This routine should be used only with factored matrices formed by in-place
8339   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8340   format).  This option can save memory, for example, when solving nonlinear
8341   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8342   ILU(0) preconditioner.
8343 
8344   One can specify in-place ILU(0) factorization by calling
8345 .vb
8346      PCType(pc,PCILU);
8347      PCFactorSeUseInPlace(pc);
8348 .ve
8349   or by using the options -pc_type ilu -pc_factor_in_place
8350 
8351   In-place factorization ILU(0) can also be used as a local
8352   solver for the blocks within the block Jacobi or additive Schwarz
8353   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8354   for details on setting local solver options.
8355 
8356   Most users should employ the `KSP` interface for linear solvers
8357   instead of working directly with matrix algebra routines such as this.
8358   See, e.g., `KSPCreate()`.
8359 
8360 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8361 @*/
8362 PetscErrorCode MatSetUnfactored(Mat mat)
8363 {
8364   PetscFunctionBegin;
8365   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8366   PetscValidType(mat, 1);
8367   MatCheckPreallocated(mat, 1);
8368   mat->factortype = MAT_FACTOR_NONE;
8369   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8370   PetscUseTypeMethod(mat, setunfactored);
8371   PetscFunctionReturn(PETSC_SUCCESS);
8372 }
8373 
8374 /*MC
8375     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8376 
8377     Synopsis:
8378     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8379 
8380     Not Collective
8381 
8382     Input Parameter:
8383 .   x - matrix
8384 
8385     Output Parameters:
8386 +   xx_v - the Fortran pointer to the array
8387 -   ierr - error code
8388 
8389     Example of Usage:
8390 .vb
8391       PetscScalar, pointer xx_v(:,:)
8392       ....
8393       call MatDenseGetArrayF90(x,xx_v,ierr)
8394       a = xx_v(3)
8395       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8396 .ve
8397 
8398     Level: advanced
8399 
8400 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8401 M*/
8402 
8403 /*MC
8404     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8405     accessed with `MatDenseGetArrayF90()`.
8406 
8407     Synopsis:
8408     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8409 
8410     Not Collective
8411 
8412     Input Parameters:
8413 +   x - matrix
8414 -   xx_v - the Fortran90 pointer to the array
8415 
8416     Output Parameter:
8417 .   ierr - error code
8418 
8419     Example of Usage:
8420 .vb
8421        PetscScalar, pointer xx_v(:,:)
8422        ....
8423        call MatDenseGetArrayF90(x,xx_v,ierr)
8424        a = xx_v(3)
8425        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8426 .ve
8427 
8428     Level: advanced
8429 
8430 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8431 M*/
8432 
8433 /*MC
8434     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8435 
8436     Synopsis:
8437     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8438 
8439     Not Collective
8440 
8441     Input Parameter:
8442 .   x - matrix
8443 
8444     Output Parameters:
8445 +   xx_v - the Fortran pointer to the array
8446 -   ierr - error code
8447 
8448     Example of Usage:
8449 .vb
8450       PetscScalar, pointer xx_v(:)
8451       ....
8452       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8453       a = xx_v(3)
8454       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8455 .ve
8456 
8457     Level: advanced
8458 
8459 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8460 M*/
8461 
8462 /*MC
8463     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8464     accessed with `MatSeqAIJGetArrayF90()`.
8465 
8466     Synopsis:
8467     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8468 
8469     Not Collective
8470 
8471     Input Parameters:
8472 +   x - matrix
8473 -   xx_v - the Fortran90 pointer to the array
8474 
8475     Output Parameter:
8476 .   ierr - error code
8477 
8478     Example of Usage:
8479 .vb
8480        PetscScalar, pointer xx_v(:)
8481        ....
8482        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8483        a = xx_v(3)
8484        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8485 .ve
8486 
8487     Level: advanced
8488 
8489 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8490 M*/
8491 
8492 /*@
8493   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8494   as the original matrix.
8495 
8496   Collective
8497 
8498   Input Parameters:
8499 + mat   - the original matrix
8500 . isrow - parallel `IS` containing the rows this processor should obtain
8501 . 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.
8502 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8503 
8504   Output Parameter:
8505 . newmat - the new submatrix, of the same type as the original matrix
8506 
8507   Level: advanced
8508 
8509   Notes:
8510   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8511 
8512   Some matrix types place restrictions on the row and column indices, such
8513   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;
8514   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8515 
8516   The index sets may not have duplicate entries.
8517 
8518   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8519   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8520   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8521   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8522   you are finished using it.
8523 
8524   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8525   the input matrix.
8526 
8527   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8528 
8529   If `isrow` and `iscol` have a nontrivial block-size, then the resulting matrix has this block-size as well. This feature
8530   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8531 
8532   Example usage:
8533   Consider the following 8x8 matrix with 34 non-zero values, that is
8534   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8535   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8536   as follows
8537 .vb
8538             1  2  0  |  0  3  0  |  0  4
8539     Proc0   0  5  6  |  7  0  0  |  8  0
8540             9  0 10  | 11  0  0  | 12  0
8541     -------------------------------------
8542            13  0 14  | 15 16 17  |  0  0
8543     Proc1   0 18  0  | 19 20 21  |  0  0
8544             0  0  0  | 22 23  0  | 24  0
8545     -------------------------------------
8546     Proc2  25 26 27  |  0  0 28  | 29  0
8547            30  0  0  | 31 32 33  |  0 34
8548 .ve
8549 
8550   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8551 
8552 .vb
8553             2  0  |  0  3  0  |  0
8554     Proc0   5  6  |  7  0  0  |  8
8555     -------------------------------
8556     Proc1  18  0  | 19 20 21  |  0
8557     -------------------------------
8558     Proc2  26 27  |  0  0 28  | 29
8559             0  0  | 31 32 33  |  0
8560 .ve
8561 
8562 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8563 @*/
8564 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8565 {
8566   PetscMPIInt size;
8567   Mat        *local;
8568   IS          iscoltmp;
8569   PetscBool   flg;
8570 
8571   PetscFunctionBegin;
8572   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8573   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8574   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8575   PetscAssertPointer(newmat, 5);
8576   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8577   PetscValidType(mat, 1);
8578   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8579   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8580 
8581   MatCheckPreallocated(mat, 1);
8582   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8583 
8584   if (!iscol || isrow == iscol) {
8585     PetscBool   stride;
8586     PetscMPIInt grabentirematrix = 0, grab;
8587     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8588     if (stride) {
8589       PetscInt first, step, n, rstart, rend;
8590       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8591       if (step == 1) {
8592         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8593         if (rstart == first) {
8594           PetscCall(ISGetLocalSize(isrow, &n));
8595           if (n == rend - rstart) grabentirematrix = 1;
8596         }
8597       }
8598     }
8599     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8600     if (grab) {
8601       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8602       if (cll == MAT_INITIAL_MATRIX) {
8603         *newmat = mat;
8604         PetscCall(PetscObjectReference((PetscObject)mat));
8605       }
8606       PetscFunctionReturn(PETSC_SUCCESS);
8607     }
8608   }
8609 
8610   if (!iscol) {
8611     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8612   } else {
8613     iscoltmp = iscol;
8614   }
8615 
8616   /* if original matrix is on just one processor then use submatrix generated */
8617   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8618     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8619     goto setproperties;
8620   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8621     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8622     *newmat = *local;
8623     PetscCall(PetscFree(local));
8624     goto setproperties;
8625   } else if (!mat->ops->createsubmatrix) {
8626     /* Create a new matrix type that implements the operation using the full matrix */
8627     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8628     switch (cll) {
8629     case MAT_INITIAL_MATRIX:
8630       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8631       break;
8632     case MAT_REUSE_MATRIX:
8633       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8634       break;
8635     default:
8636       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8637     }
8638     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8639     goto setproperties;
8640   }
8641 
8642   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8643   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8644   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8645 
8646 setproperties:
8647   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8648   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8649   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8650   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8651   PetscFunctionReturn(PETSC_SUCCESS);
8652 }
8653 
8654 /*@
8655   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8656 
8657   Not Collective
8658 
8659   Input Parameters:
8660 + A - the matrix we wish to propagate options from
8661 - B - the matrix we wish to propagate options to
8662 
8663   Level: beginner
8664 
8665   Note:
8666   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8667 
8668 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8669 @*/
8670 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8671 {
8672   PetscFunctionBegin;
8673   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8674   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8675   B->symmetry_eternal            = A->symmetry_eternal;
8676   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8677   B->symmetric                   = A->symmetric;
8678   B->structurally_symmetric      = A->structurally_symmetric;
8679   B->spd                         = A->spd;
8680   B->hermitian                   = A->hermitian;
8681   PetscFunctionReturn(PETSC_SUCCESS);
8682 }
8683 
8684 /*@
8685   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8686   used during the assembly process to store values that belong to
8687   other processors.
8688 
8689   Not Collective
8690 
8691   Input Parameters:
8692 + mat   - the matrix
8693 . size  - the initial size of the stash.
8694 - bsize - the initial size of the block-stash(if used).
8695 
8696   Options Database Keys:
8697 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8698 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8699 
8700   Level: intermediate
8701 
8702   Notes:
8703   The block-stash is used for values set with `MatSetValuesBlocked()` while
8704   the stash is used for values set with `MatSetValues()`
8705 
8706   Run with the option -info and look for output of the form
8707   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8708   to determine the appropriate value, MM, to use for size and
8709   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8710   to determine the value, BMM to use for bsize
8711 
8712 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8713 @*/
8714 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8715 {
8716   PetscFunctionBegin;
8717   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8718   PetscValidType(mat, 1);
8719   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8720   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8721   PetscFunctionReturn(PETSC_SUCCESS);
8722 }
8723 
8724 /*@
8725   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8726   the matrix
8727 
8728   Neighbor-wise Collective
8729 
8730   Input Parameters:
8731 + A - the matrix
8732 . x - the vector to be multiplied by the interpolation operator
8733 - y - the vector to be added to the result
8734 
8735   Output Parameter:
8736 . w - the resulting vector
8737 
8738   Level: intermediate
8739 
8740   Notes:
8741   `w` may be the same vector as `y`.
8742 
8743   This allows one to use either the restriction or interpolation (its transpose)
8744   matrix to do the interpolation
8745 
8746 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8747 @*/
8748 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8749 {
8750   PetscInt M, N, Ny;
8751 
8752   PetscFunctionBegin;
8753   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8754   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8755   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8756   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8757   PetscCall(MatGetSize(A, &M, &N));
8758   PetscCall(VecGetSize(y, &Ny));
8759   if (M == Ny) {
8760     PetscCall(MatMultAdd(A, x, y, w));
8761   } else {
8762     PetscCall(MatMultTransposeAdd(A, x, y, w));
8763   }
8764   PetscFunctionReturn(PETSC_SUCCESS);
8765 }
8766 
8767 /*@
8768   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8769   the matrix
8770 
8771   Neighbor-wise Collective
8772 
8773   Input Parameters:
8774 + A - the matrix
8775 - x - the vector to be interpolated
8776 
8777   Output Parameter:
8778 . y - the resulting vector
8779 
8780   Level: intermediate
8781 
8782   Note:
8783   This allows one to use either the restriction or interpolation (its transpose)
8784   matrix to do the interpolation
8785 
8786 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8787 @*/
8788 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8789 {
8790   PetscInt M, N, Ny;
8791 
8792   PetscFunctionBegin;
8793   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8794   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8795   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8796   PetscCall(MatGetSize(A, &M, &N));
8797   PetscCall(VecGetSize(y, &Ny));
8798   if (M == Ny) {
8799     PetscCall(MatMult(A, x, y));
8800   } else {
8801     PetscCall(MatMultTranspose(A, x, y));
8802   }
8803   PetscFunctionReturn(PETSC_SUCCESS);
8804 }
8805 
8806 /*@
8807   MatRestrict - $y = A*x$ or $A^T*x$
8808 
8809   Neighbor-wise Collective
8810 
8811   Input Parameters:
8812 + A - the matrix
8813 - x - the vector to be restricted
8814 
8815   Output Parameter:
8816 . y - the resulting vector
8817 
8818   Level: intermediate
8819 
8820   Note:
8821   This allows one to use either the restriction or interpolation (its transpose)
8822   matrix to do the restriction
8823 
8824 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8825 @*/
8826 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8827 {
8828   PetscInt M, N, Nx;
8829 
8830   PetscFunctionBegin;
8831   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8832   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8833   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8834   PetscCall(MatGetSize(A, &M, &N));
8835   PetscCall(VecGetSize(x, &Nx));
8836   if (M == Nx) {
8837     PetscCall(MatMultTranspose(A, x, y));
8838   } else {
8839     PetscCall(MatMult(A, x, y));
8840   }
8841   PetscFunctionReturn(PETSC_SUCCESS);
8842 }
8843 
8844 /*@
8845   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8846 
8847   Neighbor-wise Collective
8848 
8849   Input Parameters:
8850 + A - the matrix
8851 . x - the input dense matrix to be multiplied
8852 - w - the input dense matrix to be added to the result
8853 
8854   Output Parameter:
8855 . y - the output dense matrix
8856 
8857   Level: intermediate
8858 
8859   Note:
8860   This allows one to use either the restriction or interpolation (its transpose)
8861   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8862   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8863 
8864 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8865 @*/
8866 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8867 {
8868   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8869   PetscBool trans = PETSC_TRUE;
8870   MatReuse  reuse = MAT_INITIAL_MATRIX;
8871 
8872   PetscFunctionBegin;
8873   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8874   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8875   PetscValidType(x, 2);
8876   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8877   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8878   PetscCall(MatGetSize(A, &M, &N));
8879   PetscCall(MatGetSize(x, &Mx, &Nx));
8880   if (N == Mx) trans = PETSC_FALSE;
8881   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);
8882   Mo = trans ? N : M;
8883   if (*y) {
8884     PetscCall(MatGetSize(*y, &My, &Ny));
8885     if (Mo == My && Nx == Ny) {
8886       reuse = MAT_REUSE_MATRIX;
8887     } else {
8888       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);
8889       PetscCall(MatDestroy(y));
8890     }
8891   }
8892 
8893   if (w && *y == w) { /* this is to minimize changes in PCMG */
8894     PetscBool flg;
8895 
8896     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8897     if (w) {
8898       PetscInt My, Ny, Mw, Nw;
8899 
8900       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8901       PetscCall(MatGetSize(*y, &My, &Ny));
8902       PetscCall(MatGetSize(w, &Mw, &Nw));
8903       if (!flg || My != Mw || Ny != Nw) w = NULL;
8904     }
8905     if (!w) {
8906       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8907       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8908       PetscCall(PetscObjectDereference((PetscObject)w));
8909     } else {
8910       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8911     }
8912   }
8913   if (!trans) {
8914     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8915   } else {
8916     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8917   }
8918   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8919   PetscFunctionReturn(PETSC_SUCCESS);
8920 }
8921 
8922 /*@
8923   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8924 
8925   Neighbor-wise Collective
8926 
8927   Input Parameters:
8928 + A - the matrix
8929 - x - the input dense matrix
8930 
8931   Output Parameter:
8932 . y - the output dense matrix
8933 
8934   Level: intermediate
8935 
8936   Note:
8937   This allows one to use either the restriction or interpolation (its transpose)
8938   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8939   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8940 
8941 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8942 @*/
8943 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8944 {
8945   PetscFunctionBegin;
8946   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8947   PetscFunctionReturn(PETSC_SUCCESS);
8948 }
8949 
8950 /*@
8951   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8952 
8953   Neighbor-wise Collective
8954 
8955   Input Parameters:
8956 + A - the matrix
8957 - x - the input dense matrix
8958 
8959   Output Parameter:
8960 . y - the output dense matrix
8961 
8962   Level: intermediate
8963 
8964   Note:
8965   This allows one to use either the restriction or interpolation (its transpose)
8966   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8967   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8968 
8969 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8970 @*/
8971 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8972 {
8973   PetscFunctionBegin;
8974   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8975   PetscFunctionReturn(PETSC_SUCCESS);
8976 }
8977 
8978 /*@
8979   MatGetNullSpace - retrieves the null space of a matrix.
8980 
8981   Logically Collective
8982 
8983   Input Parameters:
8984 + mat    - the matrix
8985 - nullsp - the null space object
8986 
8987   Level: developer
8988 
8989 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8990 @*/
8991 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8992 {
8993   PetscFunctionBegin;
8994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8995   PetscAssertPointer(nullsp, 2);
8996   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8997   PetscFunctionReturn(PETSC_SUCCESS);
8998 }
8999 
9000 /*@C
9001   MatGetNullSpaces - gets the null spaces, transpose null spaces, and near null spaces from an array of matrices
9002 
9003   Logically Collective
9004 
9005   Input Parameters:
9006 + n   - the number of matrices
9007 - mat - the array of matrices
9008 
9009   Output Parameters:
9010 . nullsp - an array of null spaces, `NULL` for each matrix that does not have a null space, length 3 * `n`
9011 
9012   Level: developer
9013 
9014   Note:
9015   Call `MatRestoreNullspaces()` to provide these to another array of matrices
9016 
9017 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9018           `MatNullSpaceRemove()`, `MatRestoreNullSpaces()`
9019 @*/
9020 PetscErrorCode MatGetNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9021 {
9022   PetscFunctionBegin;
9023   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9024   PetscAssertPointer(mat, 2);
9025   PetscAssertPointer(nullsp, 3);
9026 
9027   PetscCall(PetscCalloc1(3 * n, nullsp));
9028   for (PetscInt i = 0; i < n; i++) {
9029     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9030     (*nullsp)[i] = mat[i]->nullsp;
9031     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[i]));
9032     (*nullsp)[n + i] = mat[i]->nearnullsp;
9033     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[n + i]));
9034     (*nullsp)[2 * n + i] = mat[i]->transnullsp;
9035     PetscCall(PetscObjectReference((PetscObject)(*nullsp)[2 * n + i]));
9036   }
9037   PetscFunctionReturn(PETSC_SUCCESS);
9038 }
9039 
9040 /*@C
9041   MatRestoreNullSpaces - sets the null spaces, transpose null spaces, and near null spaces obtained with `MatGetNullSpaces()` for an array of matrices
9042 
9043   Logically Collective
9044 
9045   Input Parameters:
9046 + n      - the number of matrices
9047 . mat    - the array of matrices
9048 - nullsp - an array of null spaces
9049 
9050   Level: developer
9051 
9052   Note:
9053   Call `MatGetNullSpaces()` to create `nullsp`
9054 
9055 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`,
9056           `MatNullSpaceRemove()`, `MatGetNullSpaces()`
9057 @*/
9058 PetscErrorCode MatRestoreNullSpaces(PetscInt n, Mat mat[], MatNullSpace *nullsp[])
9059 {
9060   PetscFunctionBegin;
9061   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of matrices %" PetscInt_FMT " must be non-negative", n);
9062   PetscAssertPointer(mat, 2);
9063   PetscAssertPointer(nullsp, 3);
9064   PetscAssertPointer(*nullsp, 3);
9065 
9066   for (PetscInt i = 0; i < n; i++) {
9067     PetscValidHeaderSpecific(mat[i], MAT_CLASSID, 2);
9068     PetscCall(MatSetNullSpace(mat[i], (*nullsp)[i]));
9069     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[i]));
9070     PetscCall(MatSetNearNullSpace(mat[i], (*nullsp)[n + i]));
9071     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[n + i]));
9072     PetscCall(MatSetTransposeNullSpace(mat[i], (*nullsp)[2 * n + i]));
9073     PetscCall(PetscObjectDereference((PetscObject)(*nullsp)[2 * n + i]));
9074   }
9075   PetscCall(PetscFree(*nullsp));
9076   PetscFunctionReturn(PETSC_SUCCESS);
9077 }
9078 
9079 /*@
9080   MatSetNullSpace - attaches a null space to a matrix.
9081 
9082   Logically Collective
9083 
9084   Input Parameters:
9085 + mat    - the matrix
9086 - nullsp - the null space object
9087 
9088   Level: advanced
9089 
9090   Notes:
9091   This null space is used by the `KSP` linear solvers to solve singular systems.
9092 
9093   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`
9094 
9095   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
9096   to zero but the linear system will still be solved in a least squares sense.
9097 
9098   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
9099   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)$.
9100   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
9101   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
9102   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$).
9103   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
9104 
9105   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
9106   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
9107   routine also automatically calls `MatSetTransposeNullSpace()`.
9108 
9109   The user should call `MatNullSpaceDestroy()`.
9110 
9111 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
9112           `KSPSetPCSide()`
9113 @*/
9114 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
9115 {
9116   PetscFunctionBegin;
9117   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9118   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9119   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9120   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
9121   mat->nullsp = nullsp;
9122   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
9123   PetscFunctionReturn(PETSC_SUCCESS);
9124 }
9125 
9126 /*@
9127   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
9128 
9129   Logically Collective
9130 
9131   Input Parameters:
9132 + mat    - the matrix
9133 - nullsp - the null space object
9134 
9135   Level: developer
9136 
9137 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
9138 @*/
9139 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
9140 {
9141   PetscFunctionBegin;
9142   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9143   PetscValidType(mat, 1);
9144   PetscAssertPointer(nullsp, 2);
9145   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
9146   PetscFunctionReturn(PETSC_SUCCESS);
9147 }
9148 
9149 /*@
9150   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
9151 
9152   Logically Collective
9153 
9154   Input Parameters:
9155 + mat    - the matrix
9156 - nullsp - the null space object
9157 
9158   Level: advanced
9159 
9160   Notes:
9161   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
9162 
9163   See `MatSetNullSpace()`
9164 
9165 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
9166 @*/
9167 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
9168 {
9169   PetscFunctionBegin;
9170   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9171   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9172   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9173   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
9174   mat->transnullsp = nullsp;
9175   PetscFunctionReturn(PETSC_SUCCESS);
9176 }
9177 
9178 /*@
9179   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
9180   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
9181 
9182   Logically Collective
9183 
9184   Input Parameters:
9185 + mat    - the matrix
9186 - nullsp - the null space object
9187 
9188   Level: advanced
9189 
9190   Notes:
9191   Overwrites any previous near null space that may have been attached
9192 
9193   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9194 
9195 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9196 @*/
9197 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9198 {
9199   PetscFunctionBegin;
9200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9201   PetscValidType(mat, 1);
9202   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9203   MatCheckPreallocated(mat, 1);
9204   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9205   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9206   mat->nearnullsp = nullsp;
9207   PetscFunctionReturn(PETSC_SUCCESS);
9208 }
9209 
9210 /*@
9211   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9212 
9213   Not Collective
9214 
9215   Input Parameter:
9216 . mat - the matrix
9217 
9218   Output Parameter:
9219 . nullsp - the null space object, `NULL` if not set
9220 
9221   Level: advanced
9222 
9223 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9224 @*/
9225 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9226 {
9227   PetscFunctionBegin;
9228   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9229   PetscValidType(mat, 1);
9230   PetscAssertPointer(nullsp, 2);
9231   MatCheckPreallocated(mat, 1);
9232   *nullsp = mat->nearnullsp;
9233   PetscFunctionReturn(PETSC_SUCCESS);
9234 }
9235 
9236 /*@
9237   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9238 
9239   Collective
9240 
9241   Input Parameters:
9242 + mat  - the matrix
9243 . row  - row/column permutation
9244 - info - information on desired factorization process
9245 
9246   Level: developer
9247 
9248   Notes:
9249   Probably really in-place only when level of fill is zero, otherwise allocates
9250   new space to store factored matrix and deletes previous memory.
9251 
9252   Most users should employ the `KSP` interface for linear solvers
9253   instead of working directly with matrix algebra routines such as this.
9254   See, e.g., `KSPCreate()`.
9255 
9256   Developer Note:
9257   The Fortran interface is not autogenerated as the
9258   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9259 
9260 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9261 @*/
9262 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9263 {
9264   PetscFunctionBegin;
9265   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9266   PetscValidType(mat, 1);
9267   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9268   PetscAssertPointer(info, 3);
9269   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9270   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9271   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9272   MatCheckPreallocated(mat, 1);
9273   PetscUseTypeMethod(mat, iccfactor, row, info);
9274   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9275   PetscFunctionReturn(PETSC_SUCCESS);
9276 }
9277 
9278 /*@
9279   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9280   ghosted ones.
9281 
9282   Not Collective
9283 
9284   Input Parameters:
9285 + mat  - the matrix
9286 - diag - the diagonal values, including ghost ones
9287 
9288   Level: developer
9289 
9290   Notes:
9291   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9292 
9293   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9294 
9295 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9296 @*/
9297 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9298 {
9299   PetscMPIInt size;
9300 
9301   PetscFunctionBegin;
9302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9303   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9304   PetscValidType(mat, 1);
9305 
9306   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9307   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9308   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9309   if (size == 1) {
9310     PetscInt n, m;
9311     PetscCall(VecGetSize(diag, &n));
9312     PetscCall(MatGetSize(mat, NULL, &m));
9313     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9314     PetscCall(MatDiagonalScale(mat, NULL, diag));
9315   } else {
9316     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9317   }
9318   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9319   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9320   PetscFunctionReturn(PETSC_SUCCESS);
9321 }
9322 
9323 /*@
9324   MatGetInertia - Gets the inertia from a factored matrix
9325 
9326   Collective
9327 
9328   Input Parameter:
9329 . mat - the matrix
9330 
9331   Output Parameters:
9332 + nneg  - number of negative eigenvalues
9333 . nzero - number of zero eigenvalues
9334 - npos  - number of positive eigenvalues
9335 
9336   Level: advanced
9337 
9338   Note:
9339   Matrix must have been factored by `MatCholeskyFactor()`
9340 
9341 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9342 @*/
9343 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9344 {
9345   PetscFunctionBegin;
9346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9347   PetscValidType(mat, 1);
9348   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9349   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9350   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9351   PetscFunctionReturn(PETSC_SUCCESS);
9352 }
9353 
9354 /*@C
9355   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9356 
9357   Neighbor-wise Collective
9358 
9359   Input Parameters:
9360 + mat - the factored matrix obtained with `MatGetFactor()`
9361 - b   - the right-hand-side vectors
9362 
9363   Output Parameter:
9364 . x - the result vectors
9365 
9366   Level: developer
9367 
9368   Note:
9369   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9370   call `MatSolves`(A,x,x).
9371 
9372 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9373 @*/
9374 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9375 {
9376   PetscFunctionBegin;
9377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9378   PetscValidType(mat, 1);
9379   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9380   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9381   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9382 
9383   MatCheckPreallocated(mat, 1);
9384   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9385   PetscUseTypeMethod(mat, solves, b, x);
9386   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9387   PetscFunctionReturn(PETSC_SUCCESS);
9388 }
9389 
9390 /*@
9391   MatIsSymmetric - Test whether a matrix is symmetric
9392 
9393   Collective
9394 
9395   Input Parameters:
9396 + A   - the matrix to test
9397 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9398 
9399   Output Parameter:
9400 . flg - the result
9401 
9402   Level: intermediate
9403 
9404   Notes:
9405   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9406 
9407   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9408 
9409   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9410   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9411 
9412 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9413           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9414 @*/
9415 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9416 {
9417   PetscFunctionBegin;
9418   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9419   PetscAssertPointer(flg, 3);
9420   if (A->symmetric != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->symmetric);
9421   else {
9422     if (A->ops->issymmetric) PetscUseTypeMethod(A, issymmetric, tol, flg);
9423     else PetscCall(MatIsTranspose(A, A, tol, flg));
9424     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9425   }
9426   PetscFunctionReturn(PETSC_SUCCESS);
9427 }
9428 
9429 /*@
9430   MatIsHermitian - Test whether a matrix is Hermitian
9431 
9432   Collective
9433 
9434   Input Parameters:
9435 + A   - the matrix to test
9436 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9437 
9438   Output Parameter:
9439 . flg - the result
9440 
9441   Level: intermediate
9442 
9443   Notes:
9444   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9445 
9446   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9447 
9448   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9449   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9450 
9451 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9452           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9453 @*/
9454 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9455 {
9456   PetscFunctionBegin;
9457   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9458   PetscAssertPointer(flg, 3);
9459   if (A->hermitian != PETSC_BOOL3_UNKNOWN) *flg = PetscBool3ToBool(A->hermitian);
9460   else {
9461     if (A->ops->ishermitian) PetscUseTypeMethod(A, ishermitian, tol, flg);
9462     else PetscCall(MatIsHermitianTranspose(A, A, tol, flg));
9463     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9464   }
9465   PetscFunctionReturn(PETSC_SUCCESS);
9466 }
9467 
9468 /*@
9469   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9470 
9471   Not Collective
9472 
9473   Input Parameter:
9474 . A - the matrix to check
9475 
9476   Output Parameters:
9477 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9478 - flg - the result (only valid if set is `PETSC_TRUE`)
9479 
9480   Level: advanced
9481 
9482   Notes:
9483   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9484   if you want it explicitly checked
9485 
9486   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9487   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9488 
9489 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9490 @*/
9491 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9492 {
9493   PetscFunctionBegin;
9494   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9495   PetscAssertPointer(set, 2);
9496   PetscAssertPointer(flg, 3);
9497   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9498     *set = PETSC_TRUE;
9499     *flg = PetscBool3ToBool(A->symmetric);
9500   } else {
9501     *set = PETSC_FALSE;
9502   }
9503   PetscFunctionReturn(PETSC_SUCCESS);
9504 }
9505 
9506 /*@
9507   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9508 
9509   Not Collective
9510 
9511   Input Parameter:
9512 . A - the matrix to check
9513 
9514   Output Parameters:
9515 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9516 - flg - the result (only valid if set is `PETSC_TRUE`)
9517 
9518   Level: advanced
9519 
9520   Notes:
9521   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9522 
9523   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9524   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9525 
9526 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9527 @*/
9528 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9529 {
9530   PetscFunctionBegin;
9531   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9532   PetscAssertPointer(set, 2);
9533   PetscAssertPointer(flg, 3);
9534   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9535     *set = PETSC_TRUE;
9536     *flg = PetscBool3ToBool(A->spd);
9537   } else {
9538     *set = PETSC_FALSE;
9539   }
9540   PetscFunctionReturn(PETSC_SUCCESS);
9541 }
9542 
9543 /*@
9544   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9545 
9546   Not Collective
9547 
9548   Input Parameter:
9549 . A - the matrix to check
9550 
9551   Output Parameters:
9552 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9553 - flg - the result (only valid if set is `PETSC_TRUE`)
9554 
9555   Level: advanced
9556 
9557   Notes:
9558   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9559   if you want it explicitly checked
9560 
9561   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9562   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9563 
9564 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9565 @*/
9566 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9567 {
9568   PetscFunctionBegin;
9569   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9570   PetscAssertPointer(set, 2);
9571   PetscAssertPointer(flg, 3);
9572   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9573     *set = PETSC_TRUE;
9574     *flg = PetscBool3ToBool(A->hermitian);
9575   } else {
9576     *set = PETSC_FALSE;
9577   }
9578   PetscFunctionReturn(PETSC_SUCCESS);
9579 }
9580 
9581 /*@
9582   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9583 
9584   Collective
9585 
9586   Input Parameter:
9587 . A - the matrix to test
9588 
9589   Output Parameter:
9590 . flg - the result
9591 
9592   Level: intermediate
9593 
9594   Notes:
9595   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9596 
9597   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
9598   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9599 
9600 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9601 @*/
9602 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9603 {
9604   PetscFunctionBegin;
9605   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9606   PetscAssertPointer(flg, 2);
9607   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9608     *flg = PetscBool3ToBool(A->structurally_symmetric);
9609   } else {
9610     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9611     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9612   }
9613   PetscFunctionReturn(PETSC_SUCCESS);
9614 }
9615 
9616 /*@
9617   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9618 
9619   Not Collective
9620 
9621   Input Parameter:
9622 . A - the matrix to check
9623 
9624   Output Parameters:
9625 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9626 - flg - the result (only valid if set is PETSC_TRUE)
9627 
9628   Level: advanced
9629 
9630   Notes:
9631   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
9632   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9633 
9634   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9635 
9636 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9637 @*/
9638 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9639 {
9640   PetscFunctionBegin;
9641   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9642   PetscAssertPointer(set, 2);
9643   PetscAssertPointer(flg, 3);
9644   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9645     *set = PETSC_TRUE;
9646     *flg = PetscBool3ToBool(A->structurally_symmetric);
9647   } else {
9648     *set = PETSC_FALSE;
9649   }
9650   PetscFunctionReturn(PETSC_SUCCESS);
9651 }
9652 
9653 /*@
9654   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9655   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9656 
9657   Not Collective
9658 
9659   Input Parameter:
9660 . mat - the matrix
9661 
9662   Output Parameters:
9663 + nstash    - the size of the stash
9664 . reallocs  - the number of additional mallocs incurred.
9665 . bnstash   - the size of the block stash
9666 - breallocs - the number of additional mallocs incurred.in the block stash
9667 
9668   Level: advanced
9669 
9670 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9671 @*/
9672 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9673 {
9674   PetscFunctionBegin;
9675   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9676   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9677   PetscFunctionReturn(PETSC_SUCCESS);
9678 }
9679 
9680 /*@
9681   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9682   parallel layout, `PetscLayout` for rows and columns
9683 
9684   Collective
9685 
9686   Input Parameter:
9687 . mat - the matrix
9688 
9689   Output Parameters:
9690 + right - (optional) vector that the matrix can be multiplied against
9691 - left  - (optional) vector that the matrix vector product can be stored in
9692 
9693   Level: advanced
9694 
9695   Notes:
9696   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()`.
9697 
9698   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9699 
9700 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9701 @*/
9702 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9703 {
9704   PetscFunctionBegin;
9705   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9706   PetscValidType(mat, 1);
9707   if (mat->ops->getvecs) {
9708     PetscUseTypeMethod(mat, getvecs, right, left);
9709   } else {
9710     if (right) {
9711       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9712       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9713       PetscCall(VecSetType(*right, mat->defaultvectype));
9714 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9715       if (mat->boundtocpu && mat->bindingpropagates) {
9716         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9717         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9718       }
9719 #endif
9720     }
9721     if (left) {
9722       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9723       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9724       PetscCall(VecSetType(*left, mat->defaultvectype));
9725 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9726       if (mat->boundtocpu && mat->bindingpropagates) {
9727         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9728         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9729       }
9730 #endif
9731     }
9732   }
9733   PetscFunctionReturn(PETSC_SUCCESS);
9734 }
9735 
9736 /*@
9737   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9738   with default values.
9739 
9740   Not Collective
9741 
9742   Input Parameter:
9743 . info - the `MatFactorInfo` data structure
9744 
9745   Level: developer
9746 
9747   Notes:
9748   The solvers are generally used through the `KSP` and `PC` objects, for example
9749   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9750 
9751   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9752 
9753 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9754 @*/
9755 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9756 {
9757   PetscFunctionBegin;
9758   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9759   PetscFunctionReturn(PETSC_SUCCESS);
9760 }
9761 
9762 /*@
9763   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9764 
9765   Collective
9766 
9767   Input Parameters:
9768 + mat - the factored matrix
9769 - is  - the index set defining the Schur indices (0-based)
9770 
9771   Level: advanced
9772 
9773   Notes:
9774   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9775 
9776   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9777 
9778   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9779 
9780 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9781           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9782 @*/
9783 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9784 {
9785   PetscErrorCode (*f)(Mat, IS);
9786 
9787   PetscFunctionBegin;
9788   PetscValidType(mat, 1);
9789   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9790   PetscValidType(is, 2);
9791   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9792   PetscCheckSameComm(mat, 1, is, 2);
9793   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9794   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9795   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9796   PetscCall(MatDestroy(&mat->schur));
9797   PetscCall((*f)(mat, is));
9798   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9799   PetscFunctionReturn(PETSC_SUCCESS);
9800 }
9801 
9802 /*@
9803   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9804 
9805   Logically Collective
9806 
9807   Input Parameters:
9808 + F      - the factored matrix obtained by calling `MatGetFactor()`
9809 . S      - location where to return the Schur complement, can be `NULL`
9810 - status - the status of the Schur complement matrix, can be `NULL`
9811 
9812   Level: advanced
9813 
9814   Notes:
9815   You must call `MatFactorSetSchurIS()` before calling this routine.
9816 
9817   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9818 
9819   The routine provides a copy of the Schur matrix stored within the solver data structures.
9820   The caller must destroy the object when it is no longer needed.
9821   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9822 
9823   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)
9824 
9825   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9826 
9827   Developer Note:
9828   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9829   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9830 
9831 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9832 @*/
9833 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9834 {
9835   PetscFunctionBegin;
9836   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9837   if (S) PetscAssertPointer(S, 2);
9838   if (status) PetscAssertPointer(status, 3);
9839   if (S) {
9840     PetscErrorCode (*f)(Mat, Mat *);
9841 
9842     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9843     if (f) {
9844       PetscCall((*f)(F, S));
9845     } else {
9846       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9847     }
9848   }
9849   if (status) *status = F->schur_status;
9850   PetscFunctionReturn(PETSC_SUCCESS);
9851 }
9852 
9853 /*@
9854   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9855 
9856   Logically Collective
9857 
9858   Input Parameters:
9859 + F      - the factored matrix obtained by calling `MatGetFactor()`
9860 . S      - location where to return the Schur complement, can be `NULL`
9861 - status - the status of the Schur complement matrix, can be `NULL`
9862 
9863   Level: advanced
9864 
9865   Notes:
9866   You must call `MatFactorSetSchurIS()` before calling this routine.
9867 
9868   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9869 
9870   The routine returns a the Schur Complement stored within the data structures of the solver.
9871 
9872   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9873 
9874   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9875 
9876   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9877 
9878   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9879 
9880 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9881 @*/
9882 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9883 {
9884   PetscFunctionBegin;
9885   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9886   if (S) {
9887     PetscAssertPointer(S, 2);
9888     *S = F->schur;
9889   }
9890   if (status) {
9891     PetscAssertPointer(status, 3);
9892     *status = F->schur_status;
9893   }
9894   PetscFunctionReturn(PETSC_SUCCESS);
9895 }
9896 
9897 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9898 {
9899   Mat S = F->schur;
9900 
9901   PetscFunctionBegin;
9902   switch (F->schur_status) {
9903   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9904   case MAT_FACTOR_SCHUR_INVERTED:
9905     if (S) {
9906       S->ops->solve             = NULL;
9907       S->ops->matsolve          = NULL;
9908       S->ops->solvetranspose    = NULL;
9909       S->ops->matsolvetranspose = NULL;
9910       S->ops->solveadd          = NULL;
9911       S->ops->solvetransposeadd = NULL;
9912       S->factortype             = MAT_FACTOR_NONE;
9913       PetscCall(PetscFree(S->solvertype));
9914     }
9915   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9916     break;
9917   default:
9918     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9919   }
9920   PetscFunctionReturn(PETSC_SUCCESS);
9921 }
9922 
9923 /*@
9924   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9925 
9926   Logically Collective
9927 
9928   Input Parameters:
9929 + F      - the factored matrix obtained by calling `MatGetFactor()`
9930 . S      - location where the Schur complement is stored
9931 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9932 
9933   Level: advanced
9934 
9935 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9936 @*/
9937 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9938 {
9939   PetscFunctionBegin;
9940   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9941   if (S) {
9942     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9943     *S = NULL;
9944   }
9945   F->schur_status = status;
9946   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9947   PetscFunctionReturn(PETSC_SUCCESS);
9948 }
9949 
9950 /*@
9951   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9952 
9953   Logically Collective
9954 
9955   Input Parameters:
9956 + F   - the factored matrix obtained by calling `MatGetFactor()`
9957 . rhs - location where the right-hand side of the Schur complement system is stored
9958 - sol - location where the solution of the Schur complement system has to be returned
9959 
9960   Level: advanced
9961 
9962   Notes:
9963   The sizes of the vectors should match the size of the Schur complement
9964 
9965   Must be called after `MatFactorSetSchurIS()`
9966 
9967 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9968 @*/
9969 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9970 {
9971   PetscFunctionBegin;
9972   PetscValidType(F, 1);
9973   PetscValidType(rhs, 2);
9974   PetscValidType(sol, 3);
9975   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9976   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9977   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9978   PetscCheckSameComm(F, 1, rhs, 2);
9979   PetscCheckSameComm(F, 1, sol, 3);
9980   PetscCall(MatFactorFactorizeSchurComplement(F));
9981   switch (F->schur_status) {
9982   case MAT_FACTOR_SCHUR_FACTORED:
9983     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9984     break;
9985   case MAT_FACTOR_SCHUR_INVERTED:
9986     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9987     break;
9988   default:
9989     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9990   }
9991   PetscFunctionReturn(PETSC_SUCCESS);
9992 }
9993 
9994 /*@
9995   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9996 
9997   Logically Collective
9998 
9999   Input Parameters:
10000 + F   - the factored matrix obtained by calling `MatGetFactor()`
10001 . rhs - location where the right-hand side of the Schur complement system is stored
10002 - sol - location where the solution of the Schur complement system has to be returned
10003 
10004   Level: advanced
10005 
10006   Notes:
10007   The sizes of the vectors should match the size of the Schur complement
10008 
10009   Must be called after `MatFactorSetSchurIS()`
10010 
10011 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
10012 @*/
10013 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
10014 {
10015   PetscFunctionBegin;
10016   PetscValidType(F, 1);
10017   PetscValidType(rhs, 2);
10018   PetscValidType(sol, 3);
10019   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10020   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
10021   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
10022   PetscCheckSameComm(F, 1, rhs, 2);
10023   PetscCheckSameComm(F, 1, sol, 3);
10024   PetscCall(MatFactorFactorizeSchurComplement(F));
10025   switch (F->schur_status) {
10026   case MAT_FACTOR_SCHUR_FACTORED:
10027     PetscCall(MatSolve(F->schur, rhs, sol));
10028     break;
10029   case MAT_FACTOR_SCHUR_INVERTED:
10030     PetscCall(MatMult(F->schur, rhs, sol));
10031     break;
10032   default:
10033     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
10034   }
10035   PetscFunctionReturn(PETSC_SUCCESS);
10036 }
10037 
10038 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
10039 #if PetscDefined(HAVE_CUDA)
10040 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
10041 #endif
10042 
10043 /* Schur status updated in the interface */
10044 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
10045 {
10046   Mat S = F->schur;
10047 
10048   PetscFunctionBegin;
10049   if (S) {
10050     PetscMPIInt size;
10051     PetscBool   isdense, isdensecuda;
10052 
10053     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
10054     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
10055     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
10056     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
10057     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
10058     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
10059     if (isdense) {
10060       PetscCall(MatSeqDenseInvertFactors_Private(S));
10061     } else if (isdensecuda) {
10062 #if defined(PETSC_HAVE_CUDA)
10063       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
10064 #endif
10065     }
10066     // HIP??????????????
10067     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
10068   }
10069   PetscFunctionReturn(PETSC_SUCCESS);
10070 }
10071 
10072 /*@
10073   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
10074 
10075   Logically Collective
10076 
10077   Input Parameter:
10078 . F - the factored matrix obtained by calling `MatGetFactor()`
10079 
10080   Level: advanced
10081 
10082   Notes:
10083   Must be called after `MatFactorSetSchurIS()`.
10084 
10085   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
10086 
10087 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
10088 @*/
10089 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
10090 {
10091   PetscFunctionBegin;
10092   PetscValidType(F, 1);
10093   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10094   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
10095   PetscCall(MatFactorFactorizeSchurComplement(F));
10096   PetscCall(MatFactorInvertSchurComplement_Private(F));
10097   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
10098   PetscFunctionReturn(PETSC_SUCCESS);
10099 }
10100 
10101 /*@
10102   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
10103 
10104   Logically Collective
10105 
10106   Input Parameter:
10107 . F - the factored matrix obtained by calling `MatGetFactor()`
10108 
10109   Level: advanced
10110 
10111   Note:
10112   Must be called after `MatFactorSetSchurIS()`
10113 
10114 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
10115 @*/
10116 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
10117 {
10118   MatFactorInfo info;
10119 
10120   PetscFunctionBegin;
10121   PetscValidType(F, 1);
10122   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
10123   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
10124   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
10125   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
10126   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
10127     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
10128   } else {
10129     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
10130   }
10131   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
10132   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
10133   PetscFunctionReturn(PETSC_SUCCESS);
10134 }
10135 
10136 /*@
10137   MatPtAP - Creates the matrix product $C = P^T * A * P$
10138 
10139   Neighbor-wise Collective
10140 
10141   Input Parameters:
10142 + A     - the matrix
10143 . P     - the projection matrix
10144 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10145 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
10146           if the result is a dense matrix this is irrelevant
10147 
10148   Output Parameter:
10149 . C - the product matrix
10150 
10151   Level: intermediate
10152 
10153   Notes:
10154   C will be created and must be destroyed by the user with `MatDestroy()`.
10155 
10156   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10157 
10158   Developer Note:
10159   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
10160 
10161 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
10162 @*/
10163 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
10164 {
10165   PetscFunctionBegin;
10166   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10167   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10168 
10169   if (scall == MAT_INITIAL_MATRIX) {
10170     PetscCall(MatProductCreate(A, P, NULL, C));
10171     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
10172     PetscCall(MatProductSetAlgorithm(*C, "default"));
10173     PetscCall(MatProductSetFill(*C, fill));
10174 
10175     (*C)->product->api_user = PETSC_TRUE;
10176     PetscCall(MatProductSetFromOptions(*C));
10177     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);
10178     PetscCall(MatProductSymbolic(*C));
10179   } else { /* scall == MAT_REUSE_MATRIX */
10180     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10181   }
10182 
10183   PetscCall(MatProductNumeric(*C));
10184   (*C)->symmetric = A->symmetric;
10185   (*C)->spd       = A->spd;
10186   PetscFunctionReturn(PETSC_SUCCESS);
10187 }
10188 
10189 /*@
10190   MatRARt - Creates the matrix product $C = R * A * R^T$
10191 
10192   Neighbor-wise Collective
10193 
10194   Input Parameters:
10195 + A     - the matrix
10196 . R     - the projection matrix
10197 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10198 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
10199           if the result is a dense matrix this is irrelevant
10200 
10201   Output Parameter:
10202 . C - the product matrix
10203 
10204   Level: intermediate
10205 
10206   Notes:
10207   C will be created and must be destroyed by the user with `MatDestroy()`.
10208 
10209   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10210 
10211   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10212   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10213   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
10214   We recommend using MatPtAP().
10215 
10216 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10217 @*/
10218 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10219 {
10220   PetscFunctionBegin;
10221   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10222   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10223 
10224   if (scall == MAT_INITIAL_MATRIX) {
10225     PetscCall(MatProductCreate(A, R, NULL, C));
10226     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10227     PetscCall(MatProductSetAlgorithm(*C, "default"));
10228     PetscCall(MatProductSetFill(*C, fill));
10229 
10230     (*C)->product->api_user = PETSC_TRUE;
10231     PetscCall(MatProductSetFromOptions(*C));
10232     PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "MatProduct %s not supported for A %s and R %s", MatProductTypes[MATPRODUCT_RARt], ((PetscObject)A)->type_name, ((PetscObject)R)->type_name);
10233     PetscCall(MatProductSymbolic(*C));
10234   } else { /* scall == MAT_REUSE_MATRIX */
10235     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10236   }
10237 
10238   PetscCall(MatProductNumeric(*C));
10239   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10240   PetscFunctionReturn(PETSC_SUCCESS);
10241 }
10242 
10243 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10244 {
10245   PetscBool flg = PETSC_TRUE;
10246 
10247   PetscFunctionBegin;
10248   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX product not supported");
10249   if (scall == MAT_INITIAL_MATRIX) {
10250     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10251     PetscCall(MatProductCreate(A, B, NULL, C));
10252     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10253     PetscCall(MatProductSetFill(*C, fill));
10254   } else { /* scall == MAT_REUSE_MATRIX */
10255     Mat_Product *product = (*C)->product;
10256 
10257     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)*C, &flg, MATSEQDENSE, MATMPIDENSE, ""));
10258     if (flg && product && product->type != ptype) {
10259       PetscCall(MatProductClear(*C));
10260       product = NULL;
10261     }
10262     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10263     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10264       PetscCheck(flg, PetscObjectComm((PetscObject)*C), PETSC_ERR_SUP, "Call MatProductCreate() first");
10265       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10266       product        = (*C)->product;
10267       product->fill  = fill;
10268       product->clear = PETSC_TRUE;
10269     } else { /* user may change input matrices A or B when MAT_REUSE_MATRIX */
10270       flg = PETSC_FALSE;
10271       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10272     }
10273   }
10274   if (flg) {
10275     (*C)->product->api_user = PETSC_TRUE;
10276     PetscCall(MatProductSetType(*C, ptype));
10277     PetscCall(MatProductSetFromOptions(*C));
10278     PetscCall(MatProductSymbolic(*C));
10279   }
10280   PetscCall(MatProductNumeric(*C));
10281   PetscFunctionReturn(PETSC_SUCCESS);
10282 }
10283 
10284 /*@
10285   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10286 
10287   Neighbor-wise Collective
10288 
10289   Input Parameters:
10290 + A     - the left matrix
10291 . B     - the right matrix
10292 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10293 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10294           if the result is a dense matrix this is irrelevant
10295 
10296   Output Parameter:
10297 . C - the product matrix
10298 
10299   Notes:
10300   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10301 
10302   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call and C was obtained from a previous
10303   call to this function with `MAT_INITIAL_MATRIX`.
10304 
10305   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10306 
10307   In the special case where matrix B (and hence C) are dense you can create the correctly sized matrix C yourself and then call this routine with `MAT_REUSE_MATRIX`,
10308   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10309 
10310   Example of Usage:
10311 .vb
10312      MatProductCreate(A,B,NULL,&C);
10313      MatProductSetType(C,MATPRODUCT_AB);
10314      MatProductSymbolic(C);
10315      MatProductNumeric(C); // compute C=A * B
10316      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10317      MatProductNumeric(C);
10318      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10319      MatProductNumeric(C);
10320 .ve
10321 
10322   Level: intermediate
10323 
10324 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10325 @*/
10326 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10327 {
10328   PetscFunctionBegin;
10329   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10330   PetscFunctionReturn(PETSC_SUCCESS);
10331 }
10332 
10333 /*@
10334   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10335 
10336   Neighbor-wise Collective
10337 
10338   Input Parameters:
10339 + A     - the left matrix
10340 . B     - the right matrix
10341 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10342 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10343 
10344   Output Parameter:
10345 . C - the product matrix
10346 
10347   Options Database Key:
10348 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10349               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10350               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10351 
10352   Level: intermediate
10353 
10354   Notes:
10355   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10356 
10357   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10358 
10359   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10360   actually needed.
10361 
10362   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10363   and for pairs of `MATMPIDENSE` matrices.
10364 
10365   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10366 
10367 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10368 @*/
10369 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10370 {
10371   PetscFunctionBegin;
10372   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10373   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10374   PetscFunctionReturn(PETSC_SUCCESS);
10375 }
10376 
10377 /*@
10378   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10379 
10380   Neighbor-wise Collective
10381 
10382   Input Parameters:
10383 + A     - the left matrix
10384 . B     - the right matrix
10385 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10386 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10387 
10388   Output Parameter:
10389 . C - the product matrix
10390 
10391   Level: intermediate
10392 
10393   Notes:
10394   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10395 
10396   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10397 
10398   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10399 
10400   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10401   actually needed.
10402 
10403   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10404   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10405 
10406 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10407 @*/
10408 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10409 {
10410   PetscFunctionBegin;
10411   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10412   PetscFunctionReturn(PETSC_SUCCESS);
10413 }
10414 
10415 /*@
10416   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10417 
10418   Neighbor-wise Collective
10419 
10420   Input Parameters:
10421 + A     - the left matrix
10422 . B     - the middle matrix
10423 . C     - the right matrix
10424 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10425 - fill  - expected fill as ratio of nnz(D)/(nnz(A) + nnz(B)+nnz(C)), use `PETSC_DEFAULT` if you do not have a good estimate
10426           if the result is a dense matrix this is irrelevant
10427 
10428   Output Parameter:
10429 . D - the product matrix
10430 
10431   Level: intermediate
10432 
10433   Notes:
10434   Unless `scall` is `MAT_REUSE_MATRIX` `D` will be created.
10435 
10436   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10437 
10438   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10439 
10440   To determine the correct fill value, run with `-info` and search for the string "Fill ratio" to see the value
10441   actually needed.
10442 
10443   If you have many matrices with the same non-zero structure to multiply, you
10444   should use `MAT_REUSE_MATRIX` in all calls but the first
10445 
10446 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10447 @*/
10448 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10449 {
10450   PetscFunctionBegin;
10451   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10452   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10453 
10454   if (scall == MAT_INITIAL_MATRIX) {
10455     PetscCall(MatProductCreate(A, B, C, D));
10456     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10457     PetscCall(MatProductSetAlgorithm(*D, "default"));
10458     PetscCall(MatProductSetFill(*D, fill));
10459 
10460     (*D)->product->api_user = PETSC_TRUE;
10461     PetscCall(MatProductSetFromOptions(*D));
10462     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,
10463                ((PetscObject)C)->type_name);
10464     PetscCall(MatProductSymbolic(*D));
10465   } else { /* user may change input matrices when REUSE */
10466     PetscCall(MatProductReplaceMats(A, B, C, *D));
10467   }
10468   PetscCall(MatProductNumeric(*D));
10469   PetscFunctionReturn(PETSC_SUCCESS);
10470 }
10471 
10472 /*@
10473   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10474 
10475   Collective
10476 
10477   Input Parameters:
10478 + mat      - the matrix
10479 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10480 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10481 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10482 
10483   Output Parameter:
10484 . matredundant - redundant matrix
10485 
10486   Level: advanced
10487 
10488   Notes:
10489   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10490   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10491 
10492   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10493   calling it.
10494 
10495   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10496 
10497 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10498 @*/
10499 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10500 {
10501   MPI_Comm       comm;
10502   PetscMPIInt    size;
10503   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10504   Mat_Redundant *redund     = NULL;
10505   PetscSubcomm   psubcomm   = NULL;
10506   MPI_Comm       subcomm_in = subcomm;
10507   Mat           *matseq;
10508   IS             isrow, iscol;
10509   PetscBool      newsubcomm = PETSC_FALSE;
10510 
10511   PetscFunctionBegin;
10512   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10513   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10514     PetscAssertPointer(*matredundant, 5);
10515     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10516   }
10517 
10518   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10519   if (size == 1 || nsubcomm == 1) {
10520     if (reuse == MAT_INITIAL_MATRIX) {
10521       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10522     } else {
10523       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");
10524       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10525     }
10526     PetscFunctionReturn(PETSC_SUCCESS);
10527   }
10528 
10529   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10530   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10531   MatCheckPreallocated(mat, 1);
10532 
10533   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10534   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10535     /* create psubcomm, then get subcomm */
10536     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10537     PetscCallMPI(MPI_Comm_size(comm, &size));
10538     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10539 
10540     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10541     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10542     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10543     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10544     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10545     newsubcomm = PETSC_TRUE;
10546     PetscCall(PetscSubcommDestroy(&psubcomm));
10547   }
10548 
10549   /* get isrow, iscol and a local sequential matrix matseq[0] */
10550   if (reuse == MAT_INITIAL_MATRIX) {
10551     mloc_sub = PETSC_DECIDE;
10552     nloc_sub = PETSC_DECIDE;
10553     if (bs < 1) {
10554       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10555       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10556     } else {
10557       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10558       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10559     }
10560     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10561     rstart = rend - mloc_sub;
10562     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10563     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10564     PetscCall(ISSetIdentity(iscol));
10565   } else { /* reuse == MAT_REUSE_MATRIX */
10566     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");
10567     /* retrieve subcomm */
10568     PetscCall(PetscObjectGetComm((PetscObject)*matredundant, &subcomm));
10569     redund = (*matredundant)->redundant;
10570     isrow  = redund->isrow;
10571     iscol  = redund->iscol;
10572     matseq = redund->matseq;
10573   }
10574   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10575 
10576   /* get matredundant over subcomm */
10577   if (reuse == MAT_INITIAL_MATRIX) {
10578     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10579 
10580     /* create a supporting struct and attach it to C for reuse */
10581     PetscCall(PetscNew(&redund));
10582     (*matredundant)->redundant = redund;
10583     redund->isrow              = isrow;
10584     redund->iscol              = iscol;
10585     redund->matseq             = matseq;
10586     if (newsubcomm) {
10587       redund->subcomm = subcomm;
10588     } else {
10589       redund->subcomm = MPI_COMM_NULL;
10590     }
10591   } else {
10592     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10593   }
10594 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10595   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10596     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10597     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10598   }
10599 #endif
10600   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10601   PetscFunctionReturn(PETSC_SUCCESS);
10602 }
10603 
10604 /*@C
10605   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10606   a given `Mat`. Each submatrix can span multiple procs.
10607 
10608   Collective
10609 
10610   Input Parameters:
10611 + mat     - the matrix
10612 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10613 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10614 
10615   Output Parameter:
10616 . subMat - parallel sub-matrices each spanning a given `subcomm`
10617 
10618   Level: advanced
10619 
10620   Notes:
10621   The submatrix partition across processors is dictated by `subComm` a
10622   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10623   is not restricted to be grouped with consecutive original MPI processes.
10624 
10625   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10626   map directly to the layout of the original matrix [wrt the local
10627   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10628   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10629   the `subMat`. However the offDiagMat looses some columns - and this is
10630   reconstructed with `MatSetValues()`
10631 
10632   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10633 
10634 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10635 @*/
10636 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10637 {
10638   PetscMPIInt commsize, subCommSize;
10639 
10640   PetscFunctionBegin;
10641   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10642   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10643   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10644 
10645   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");
10646   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10647   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10648   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10649   PetscFunctionReturn(PETSC_SUCCESS);
10650 }
10651 
10652 /*@
10653   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10654 
10655   Not Collective
10656 
10657   Input Parameters:
10658 + mat   - matrix to extract local submatrix from
10659 . isrow - local row indices for submatrix
10660 - iscol - local column indices for submatrix
10661 
10662   Output Parameter:
10663 . submat - the submatrix
10664 
10665   Level: intermediate
10666 
10667   Notes:
10668   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10669 
10670   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10671   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10672 
10673   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10674   `MatSetValuesBlockedLocal()` will also be implemented.
10675 
10676   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10677   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10678 
10679 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10680 @*/
10681 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10682 {
10683   PetscFunctionBegin;
10684   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10685   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10686   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10687   PetscCheckSameComm(isrow, 2, iscol, 3);
10688   PetscAssertPointer(submat, 4);
10689   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10690 
10691   if (mat->ops->getlocalsubmatrix) {
10692     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10693   } else {
10694     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10695   }
10696   PetscFunctionReturn(PETSC_SUCCESS);
10697 }
10698 
10699 /*@
10700   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10701 
10702   Not Collective
10703 
10704   Input Parameters:
10705 + mat    - matrix to extract local submatrix from
10706 . isrow  - local row indices for submatrix
10707 . iscol  - local column indices for submatrix
10708 - submat - the submatrix
10709 
10710   Level: intermediate
10711 
10712 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10713 @*/
10714 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10715 {
10716   PetscFunctionBegin;
10717   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10718   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10719   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10720   PetscCheckSameComm(isrow, 2, iscol, 3);
10721   PetscAssertPointer(submat, 4);
10722   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10723 
10724   if (mat->ops->restorelocalsubmatrix) {
10725     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10726   } else {
10727     PetscCall(MatDestroy(submat));
10728   }
10729   *submat = NULL;
10730   PetscFunctionReturn(PETSC_SUCCESS);
10731 }
10732 
10733 /*@
10734   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10735 
10736   Collective
10737 
10738   Input Parameter:
10739 . mat - the matrix
10740 
10741   Output Parameter:
10742 . is - if any rows have zero diagonals this contains the list of them
10743 
10744   Level: developer
10745 
10746 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10747 @*/
10748 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10749 {
10750   PetscFunctionBegin;
10751   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10752   PetscValidType(mat, 1);
10753   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10754   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10755 
10756   if (!mat->ops->findzerodiagonals) {
10757     Vec                diag;
10758     const PetscScalar *a;
10759     PetscInt          *rows;
10760     PetscInt           rStart, rEnd, r, nrow = 0;
10761 
10762     PetscCall(MatCreateVecs(mat, &diag, NULL));
10763     PetscCall(MatGetDiagonal(mat, diag));
10764     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10765     PetscCall(VecGetArrayRead(diag, &a));
10766     for (r = 0; r < rEnd - rStart; ++r)
10767       if (a[r] == 0.0) ++nrow;
10768     PetscCall(PetscMalloc1(nrow, &rows));
10769     nrow = 0;
10770     for (r = 0; r < rEnd - rStart; ++r)
10771       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10772     PetscCall(VecRestoreArrayRead(diag, &a));
10773     PetscCall(VecDestroy(&diag));
10774     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10775   } else {
10776     PetscUseTypeMethod(mat, findzerodiagonals, is);
10777   }
10778   PetscFunctionReturn(PETSC_SUCCESS);
10779 }
10780 
10781 /*@
10782   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10783 
10784   Collective
10785 
10786   Input Parameter:
10787 . mat - the matrix
10788 
10789   Output Parameter:
10790 . is - contains the list of rows with off block diagonal entries
10791 
10792   Level: developer
10793 
10794 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10795 @*/
10796 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10797 {
10798   PetscFunctionBegin;
10799   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10800   PetscValidType(mat, 1);
10801   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10802   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10803 
10804   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10805   PetscFunctionReturn(PETSC_SUCCESS);
10806 }
10807 
10808 /*@C
10809   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10810 
10811   Collective; No Fortran Support
10812 
10813   Input Parameter:
10814 . mat - the matrix
10815 
10816   Output Parameter:
10817 . values - the block inverses in column major order (FORTRAN-like)
10818 
10819   Level: advanced
10820 
10821   Notes:
10822   The size of the blocks is determined by the block size of the matrix.
10823 
10824   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10825 
10826   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10827 
10828 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10829 @*/
10830 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar *values[])
10831 {
10832   PetscFunctionBegin;
10833   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10834   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10835   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10836   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10837   PetscFunctionReturn(PETSC_SUCCESS);
10838 }
10839 
10840 /*@
10841   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10842 
10843   Collective; No Fortran Support
10844 
10845   Input Parameters:
10846 + mat     - the matrix
10847 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10848 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10849 
10850   Output Parameter:
10851 . values - the block inverses in column major order (FORTRAN-like)
10852 
10853   Level: advanced
10854 
10855   Notes:
10856   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10857 
10858   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10859 
10860 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10861 @*/
10862 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt bsizes[], PetscScalar values[])
10863 {
10864   PetscFunctionBegin;
10865   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10866   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10867   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10868   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10869   PetscFunctionReturn(PETSC_SUCCESS);
10870 }
10871 
10872 /*@
10873   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10874 
10875   Collective
10876 
10877   Input Parameters:
10878 + A - the matrix
10879 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10880 
10881   Level: advanced
10882 
10883   Note:
10884   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10885 
10886 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10887 @*/
10888 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10889 {
10890   const PetscScalar *vals;
10891   PetscInt          *dnnz;
10892   PetscInt           m, rstart, rend, bs, i, j;
10893 
10894   PetscFunctionBegin;
10895   PetscCall(MatInvertBlockDiagonal(A, &vals));
10896   PetscCall(MatGetBlockSize(A, &bs));
10897   PetscCall(MatGetLocalSize(A, &m, NULL));
10898   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10899   PetscCall(PetscMalloc1(m / bs, &dnnz));
10900   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10901   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10902   PetscCall(PetscFree(dnnz));
10903   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10904   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10905   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10906   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10907   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10908   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10909   PetscFunctionReturn(PETSC_SUCCESS);
10910 }
10911 
10912 /*@
10913   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10914   via `MatTransposeColoringCreate()`.
10915 
10916   Collective
10917 
10918   Input Parameter:
10919 . c - coloring context
10920 
10921   Level: intermediate
10922 
10923 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10924 @*/
10925 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10926 {
10927   MatTransposeColoring matcolor = *c;
10928 
10929   PetscFunctionBegin;
10930   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10931   if (--((PetscObject)matcolor)->refct > 0) {
10932     matcolor = NULL;
10933     PetscFunctionReturn(PETSC_SUCCESS);
10934   }
10935 
10936   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10937   PetscCall(PetscFree(matcolor->rows));
10938   PetscCall(PetscFree(matcolor->den2sp));
10939   PetscCall(PetscFree(matcolor->colorforcol));
10940   PetscCall(PetscFree(matcolor->columns));
10941   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10942   PetscCall(PetscHeaderDestroy(c));
10943   PetscFunctionReturn(PETSC_SUCCESS);
10944 }
10945 
10946 /*@
10947   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10948   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10949   `MatTransposeColoring` to sparse `B`.
10950 
10951   Collective
10952 
10953   Input Parameters:
10954 + coloring - coloring context created with `MatTransposeColoringCreate()`
10955 - B        - sparse matrix
10956 
10957   Output Parameter:
10958 . Btdense - dense matrix $B^T$
10959 
10960   Level: developer
10961 
10962   Note:
10963   These are used internally for some implementations of `MatRARt()`
10964 
10965 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10966 @*/
10967 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10968 {
10969   PetscFunctionBegin;
10970   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10971   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10972   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10973 
10974   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10975   PetscFunctionReturn(PETSC_SUCCESS);
10976 }
10977 
10978 /*@
10979   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10980   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10981   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10982   $C_{sp}$ from $C_{den}$.
10983 
10984   Collective
10985 
10986   Input Parameters:
10987 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10988 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10989 
10990   Output Parameter:
10991 . Csp - sparse matrix
10992 
10993   Level: developer
10994 
10995   Note:
10996   These are used internally for some implementations of `MatRARt()`
10997 
10998 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10999 @*/
11000 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
11001 {
11002   PetscFunctionBegin;
11003   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
11004   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
11005   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
11006 
11007   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
11008   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
11009   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
11010   PetscFunctionReturn(PETSC_SUCCESS);
11011 }
11012 
11013 /*@
11014   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
11015 
11016   Collective
11017 
11018   Input Parameters:
11019 + mat        - the matrix product C
11020 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
11021 
11022   Output Parameter:
11023 . color - the new coloring context
11024 
11025   Level: intermediate
11026 
11027 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
11028           `MatTransColoringApplyDenToSp()`
11029 @*/
11030 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
11031 {
11032   MatTransposeColoring c;
11033   MPI_Comm             comm;
11034 
11035   PetscFunctionBegin;
11036   PetscAssertPointer(color, 3);
11037 
11038   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11039   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
11040   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
11041   c->ctype = iscoloring->ctype;
11042   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
11043   *color = c;
11044   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
11045   PetscFunctionReturn(PETSC_SUCCESS);
11046 }
11047 
11048 /*@
11049   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
11050   matrix has had new nonzero locations added to (or removed from) the matrix since the previous call, the value will be larger.
11051 
11052   Not Collective
11053 
11054   Input Parameter:
11055 . mat - the matrix
11056 
11057   Output Parameter:
11058 . state - the current state
11059 
11060   Level: intermediate
11061 
11062   Notes:
11063   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
11064   different matrices
11065 
11066   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
11067 
11068   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
11069 
11070 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
11071 @*/
11072 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
11073 {
11074   PetscFunctionBegin;
11075   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11076   *state = mat->nonzerostate;
11077   PetscFunctionReturn(PETSC_SUCCESS);
11078 }
11079 
11080 /*@
11081   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
11082   matrices from each processor
11083 
11084   Collective
11085 
11086   Input Parameters:
11087 + comm   - the communicators the parallel matrix will live on
11088 . seqmat - the input sequential matrices
11089 . n      - number of local columns (or `PETSC_DECIDE`)
11090 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11091 
11092   Output Parameter:
11093 . mpimat - the parallel matrix generated
11094 
11095   Level: developer
11096 
11097   Note:
11098   The number of columns of the matrix in EACH processor MUST be the same.
11099 
11100 .seealso: [](ch_matrices), `Mat`
11101 @*/
11102 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
11103 {
11104   PetscMPIInt size;
11105 
11106   PetscFunctionBegin;
11107   PetscCallMPI(MPI_Comm_size(comm, &size));
11108   if (size == 1) {
11109     if (reuse == MAT_INITIAL_MATRIX) {
11110       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
11111     } else {
11112       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
11113     }
11114     PetscFunctionReturn(PETSC_SUCCESS);
11115   }
11116 
11117   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");
11118 
11119   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
11120   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
11121   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
11122   PetscFunctionReturn(PETSC_SUCCESS);
11123 }
11124 
11125 /*@
11126   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
11127 
11128   Collective
11129 
11130   Input Parameters:
11131 + A - the matrix to create subdomains from
11132 - N - requested number of subdomains
11133 
11134   Output Parameters:
11135 + n   - number of subdomains resulting on this MPI process
11136 - iss - `IS` list with indices of subdomains on this MPI process
11137 
11138   Level: advanced
11139 
11140   Note:
11141   The number of subdomains must be smaller than the communicator size
11142 
11143 .seealso: [](ch_matrices), `Mat`, `IS`
11144 @*/
11145 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
11146 {
11147   MPI_Comm    comm, subcomm;
11148   PetscMPIInt size, rank, color;
11149   PetscInt    rstart, rend, k;
11150 
11151   PetscFunctionBegin;
11152   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
11153   PetscCallMPI(MPI_Comm_size(comm, &size));
11154   PetscCallMPI(MPI_Comm_rank(comm, &rank));
11155   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);
11156   *n    = 1;
11157   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
11158   color = rank / k;
11159   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
11160   PetscCall(PetscMalloc1(1, iss));
11161   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
11162   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
11163   PetscCallMPI(MPI_Comm_free(&subcomm));
11164   PetscFunctionReturn(PETSC_SUCCESS);
11165 }
11166 
11167 /*@
11168   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
11169 
11170   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
11171   If they are not the same, uses `MatMatMatMult()`.
11172 
11173   Once the coarse grid problem is constructed, correct for interpolation operators
11174   that are not of full rank, which can legitimately happen in the case of non-nested
11175   geometric multigrid.
11176 
11177   Input Parameters:
11178 + restrct     - restriction operator
11179 . dA          - fine grid matrix
11180 . interpolate - interpolation operator
11181 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11182 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
11183 
11184   Output Parameter:
11185 . A - the Galerkin coarse matrix
11186 
11187   Options Database Key:
11188 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11189 
11190   Level: developer
11191 
11192 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11193 @*/
11194 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11195 {
11196   IS  zerorows;
11197   Vec diag;
11198 
11199   PetscFunctionBegin;
11200   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11201   /* Construct the coarse grid matrix */
11202   if (interpolate == restrct) {
11203     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11204   } else {
11205     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11206   }
11207 
11208   /* If the interpolation matrix is not of full rank, A will have zero rows.
11209      This can legitimately happen in the case of non-nested geometric multigrid.
11210      In that event, we set the rows of the matrix to the rows of the identity,
11211      ignoring the equations (as the RHS will also be zero). */
11212 
11213   PetscCall(MatFindZeroRows(*A, &zerorows));
11214 
11215   if (zerorows != NULL) { /* if there are any zero rows */
11216     PetscCall(MatCreateVecs(*A, &diag, NULL));
11217     PetscCall(MatGetDiagonal(*A, diag));
11218     PetscCall(VecISSet(diag, zerorows, 1.0));
11219     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11220     PetscCall(VecDestroy(&diag));
11221     PetscCall(ISDestroy(&zerorows));
11222   }
11223   PetscFunctionReturn(PETSC_SUCCESS);
11224 }
11225 
11226 /*@C
11227   MatSetOperation - Allows user to set a matrix operation for any matrix type
11228 
11229   Logically Collective
11230 
11231   Input Parameters:
11232 + mat - the matrix
11233 . op  - the name of the operation
11234 - f   - the function that provides the operation
11235 
11236   Level: developer
11237 
11238   Example Usage:
11239 .vb
11240   extern PetscErrorCode usermult(Mat, Vec, Vec);
11241 
11242   PetscCall(MatCreateXXX(comm, ..., &A));
11243   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11244 .ve
11245 
11246   Notes:
11247   See the file `include/petscmat.h` for a complete list of matrix
11248   operations, which all have the form MATOP_<OPERATION>, where
11249   <OPERATION> is the name (in all capital letters) of the
11250   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11251 
11252   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11253   sequence as the usual matrix interface routines, since they
11254   are intended to be accessed via the usual matrix interface
11255   routines, e.g.,
11256 .vb
11257   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11258 .ve
11259 
11260   In particular each function MUST return `PETSC_SUCCESS` on success and
11261   nonzero on failure.
11262 
11263   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11264 
11265 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11266 @*/
11267 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11268 {
11269   PetscFunctionBegin;
11270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11271   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))mat->ops->view) mat->ops->viewnative = mat->ops->view;
11272   (((void (**)(void))mat->ops)[op]) = f;
11273   PetscFunctionReturn(PETSC_SUCCESS);
11274 }
11275 
11276 /*@C
11277   MatGetOperation - Gets a matrix operation for any matrix type.
11278 
11279   Not Collective
11280 
11281   Input Parameters:
11282 + mat - the matrix
11283 - op  - the name of the operation
11284 
11285   Output Parameter:
11286 . f - the function that provides the operation
11287 
11288   Level: developer
11289 
11290   Example Usage:
11291 .vb
11292   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11293 
11294   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11295 .ve
11296 
11297   Notes:
11298   See the file include/petscmat.h for a complete list of matrix
11299   operations, which all have the form MATOP_<OPERATION>, where
11300   <OPERATION> is the name (in all capital letters) of the
11301   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11302 
11303   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11304 
11305 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11306 @*/
11307 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11308 {
11309   PetscFunctionBegin;
11310   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11311   *f = (((void (**)(void))mat->ops)[op]);
11312   PetscFunctionReturn(PETSC_SUCCESS);
11313 }
11314 
11315 /*@
11316   MatHasOperation - Determines whether the given matrix supports the particular operation.
11317 
11318   Not Collective
11319 
11320   Input Parameters:
11321 + mat - the matrix
11322 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11323 
11324   Output Parameter:
11325 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11326 
11327   Level: advanced
11328 
11329   Note:
11330   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11331 
11332 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11333 @*/
11334 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11335 {
11336   PetscFunctionBegin;
11337   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11338   PetscAssertPointer(has, 3);
11339   if (mat->ops->hasoperation) {
11340     PetscUseTypeMethod(mat, hasoperation, op, has);
11341   } else {
11342     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11343     else {
11344       *has = PETSC_FALSE;
11345       if (op == MATOP_CREATE_SUBMATRIX) {
11346         PetscMPIInt size;
11347 
11348         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11349         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11350       }
11351     }
11352   }
11353   PetscFunctionReturn(PETSC_SUCCESS);
11354 }
11355 
11356 /*@
11357   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11358 
11359   Collective
11360 
11361   Input Parameter:
11362 . mat - the matrix
11363 
11364   Output Parameter:
11365 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11366 
11367   Level: beginner
11368 
11369 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11370 @*/
11371 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11372 {
11373   PetscFunctionBegin;
11374   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11375   PetscValidType(mat, 1);
11376   PetscAssertPointer(cong, 2);
11377   if (!mat->rmap || !mat->cmap) {
11378     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11379     PetscFunctionReturn(PETSC_SUCCESS);
11380   }
11381   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11382     PetscCall(PetscLayoutSetUp(mat->rmap));
11383     PetscCall(PetscLayoutSetUp(mat->cmap));
11384     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11385     if (*cong) mat->congruentlayouts = 1;
11386     else mat->congruentlayouts = 0;
11387   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11388   PetscFunctionReturn(PETSC_SUCCESS);
11389 }
11390 
11391 PetscErrorCode MatSetInf(Mat A)
11392 {
11393   PetscFunctionBegin;
11394   PetscUseTypeMethod(A, setinf);
11395   PetscFunctionReturn(PETSC_SUCCESS);
11396 }
11397 
11398 /*@
11399   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
11400   and possibly removes small values from the graph structure.
11401 
11402   Collective
11403 
11404   Input Parameters:
11405 + A       - the matrix
11406 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11407 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11408 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11409 . num_idx - size of 'index' array
11410 - index   - array of block indices to use for graph strength of connection weight
11411 
11412   Output Parameter:
11413 . graph - the resulting graph
11414 
11415   Level: advanced
11416 
11417 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11418 @*/
11419 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11420 {
11421   PetscFunctionBegin;
11422   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11423   PetscValidType(A, 1);
11424   PetscValidLogicalCollectiveBool(A, scale, 3);
11425   PetscAssertPointer(graph, 7);
11426   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11427   PetscFunctionReturn(PETSC_SUCCESS);
11428 }
11429 
11430 /*@
11431   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11432   meaning the same memory is used for the matrix, and no new memory is allocated.
11433 
11434   Collective
11435 
11436   Input Parameters:
11437 + A    - the matrix
11438 - 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
11439 
11440   Level: intermediate
11441 
11442   Developer Note:
11443   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11444   of the arrays in the data structure are unneeded.
11445 
11446 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11447 @*/
11448 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11449 {
11450   PetscFunctionBegin;
11451   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11452   PetscUseTypeMethod(A, eliminatezeros, keep);
11453   PetscFunctionReturn(PETSC_SUCCESS);
11454 }
11455