xref: /petsc/src/mat/interface/matrix.c (revision cac3c07dbc4e95423e22cb699bb64807a71d0bfe)
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;
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 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
269  @*/
270 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
271 {
272   PetscFunctionBegin;
273   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
274   PetscValidType(mat, 1);
275   PetscAssertPointer(keptrows, 2);
276   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
277   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
278   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
279   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
280   PetscFunctionReturn(PETSC_SUCCESS);
281 }
282 
283 /*@
284   MatFindZeroRows - Locate all rows that are completely zero in the matrix
285 
286   Input Parameter:
287 . mat - the matrix
288 
289   Output Parameter:
290 . zerorows - the rows that are completely zero
291 
292   Level: intermediate
293 
294   Note:
295   `zerorows` is set to `NULL` if no rows are zero.
296 
297 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
298  @*/
299 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
300 {
301   IS       keptrows;
302   PetscInt m, n;
303 
304   PetscFunctionBegin;
305   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
306   PetscValidType(mat, 1);
307   PetscAssertPointer(zerorows, 2);
308   PetscCall(MatFindNonzeroRows(mat, &keptrows));
309   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
310      In keeping with this convention, we set zerorows to NULL if there are no zero
311      rows. */
312   if (keptrows == NULL) {
313     *zerorows = NULL;
314   } else {
315     PetscCall(MatGetOwnershipRange(mat, &m, &n));
316     PetscCall(ISComplement(keptrows, m, n, zerorows));
317     PetscCall(ISDestroy(&keptrows));
318   }
319   PetscFunctionReturn(PETSC_SUCCESS);
320 }
321 
322 /*@
323   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
324 
325   Not Collective
326 
327   Input Parameter:
328 . A - the matrix
329 
330   Output Parameter:
331 . a - the diagonal part (which is a SEQUENTIAL matrix)
332 
333   Level: advanced
334 
335   Notes:
336   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
337 
338   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
339 
340 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
341 @*/
342 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
343 {
344   PetscFunctionBegin;
345   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
346   PetscValidType(A, 1);
347   PetscAssertPointer(a, 2);
348   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
349   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
350   else {
351     PetscMPIInt size;
352 
353     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
354     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
355     *a = A;
356   }
357   PetscFunctionReturn(PETSC_SUCCESS);
358 }
359 
360 /*@
361   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
362 
363   Collective
364 
365   Input Parameter:
366 . mat - the matrix
367 
368   Output Parameter:
369 . trace - the sum of the diagonal entries
370 
371   Level: advanced
372 
373 .seealso: [](ch_matrices), `Mat`
374 @*/
375 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
376 {
377   Vec diag;
378 
379   PetscFunctionBegin;
380   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
381   PetscAssertPointer(trace, 2);
382   PetscCall(MatCreateVecs(mat, &diag, NULL));
383   PetscCall(MatGetDiagonal(mat, diag));
384   PetscCall(VecSum(diag, trace));
385   PetscCall(VecDestroy(&diag));
386   PetscFunctionReturn(PETSC_SUCCESS);
387 }
388 
389 /*@
390   MatRealPart - Zeros out the imaginary part of the matrix
391 
392   Logically Collective
393 
394   Input Parameter:
395 . mat - the matrix
396 
397   Level: advanced
398 
399 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
400 @*/
401 PetscErrorCode MatRealPart(Mat mat)
402 {
403   PetscFunctionBegin;
404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
405   PetscValidType(mat, 1);
406   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
407   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
408   MatCheckPreallocated(mat, 1);
409   PetscUseTypeMethod(mat, realpart);
410   PetscFunctionReturn(PETSC_SUCCESS);
411 }
412 
413 /*@C
414   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
415 
416   Collective
417 
418   Input Parameter:
419 . mat - the matrix
420 
421   Output Parameters:
422 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each matrix block)
423 - ghosts  - the global indices of the ghost points
424 
425   Level: advanced
426 
427   Note:
428   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()` or `VecCreateGhostBlock()`
429 
430 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`, `VecCreateGhostBlock()`
431 @*/
432 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
433 {
434   PetscFunctionBegin;
435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
436   PetscValidType(mat, 1);
437   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
438   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
439   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
440   else {
441     if (nghosts) *nghosts = 0;
442     if (ghosts) *ghosts = NULL;
443   }
444   PetscFunctionReturn(PETSC_SUCCESS);
445 }
446 
447 /*@
448   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
449 
450   Logically Collective
451 
452   Input Parameter:
453 . mat - the matrix
454 
455   Level: advanced
456 
457 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
458 @*/
459 PetscErrorCode MatImaginaryPart(Mat mat)
460 {
461   PetscFunctionBegin;
462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
463   PetscValidType(mat, 1);
464   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
465   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
466   MatCheckPreallocated(mat, 1);
467   PetscUseTypeMethod(mat, imaginarypart);
468   PetscFunctionReturn(PETSC_SUCCESS);
469 }
470 
471 /*@
472   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices) in the nonzero structure
473 
474   Not Collective
475 
476   Input Parameter:
477 . mat - the matrix
478 
479   Output Parameters:
480 + missing - is any diagonal entry missing
481 - dd      - first diagonal entry that is missing (optional) on this process
482 
483   Level: advanced
484 
485   Note:
486   This does not return diagonal entries that are in the nonzero structure but happen to have a zero numerical value
487 
488 .seealso: [](ch_matrices), `Mat`
489 @*/
490 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
491 {
492   PetscFunctionBegin;
493   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
494   PetscValidType(mat, 1);
495   PetscAssertPointer(missing, 2);
496   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
497   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
498   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
499   PetscFunctionReturn(PETSC_SUCCESS);
500 }
501 
502 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
503 /*@C
504   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
505   for each row that you get to ensure that your application does
506   not bleed memory.
507 
508   Not Collective
509 
510   Input Parameters:
511 + mat - the matrix
512 - row - the row to get
513 
514   Output Parameters:
515 + ncols - if not `NULL`, the number of nonzeros in `row`
516 . cols  - if not `NULL`, the column numbers
517 - vals  - if not `NULL`, the numerical values
518 
519   Level: advanced
520 
521   Notes:
522   This routine is provided for people who need to have direct access
523   to the structure of a matrix.  We hope that we provide enough
524   high-level matrix routines that few users will need it.
525 
526   `MatGetRow()` always returns 0-based column indices, regardless of
527   whether the internal representation is 0-based (default) or 1-based.
528 
529   For better efficiency, set `cols` and/or `vals` to `NULL` if you do
530   not wish to extract these quantities.
531 
532   The user can only examine the values extracted with `MatGetRow()`;
533   the values CANNOT be altered.  To change the matrix entries, one
534   must use `MatSetValues()`.
535 
536   You can only have one call to `MatGetRow()` outstanding for a particular
537   matrix at a time, per processor. `MatGetRow()` can only obtain rows
538   associated with the given processor, it cannot get rows from the
539   other processors; for that we suggest using `MatCreateSubMatrices()`, then
540   `MatGetRow()` on the submatrix. The row index passed to `MatGetRow()`
541   is in the global number of rows.
542 
543   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
544 
545   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
546 
547   Fortran Note:
548   The calling sequence is
549 .vb
550    MatGetRow(matrix,row,ncols,cols,values,ierr)
551          Mat     matrix (input)
552          integer row    (input)
553          integer ncols  (output)
554          integer cols(maxcols) (output)
555          double precision (or double complex) values(maxcols) output
556 .ve
557   where maxcols >= maximum nonzeros in any row of the matrix.
558 
559 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
560 @*/
561 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
562 {
563   PetscInt incols;
564 
565   PetscFunctionBegin;
566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
567   PetscValidType(mat, 1);
568   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
569   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
570   MatCheckPreallocated(mat, 1);
571   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);
572   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
573   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
574   if (ncols) *ncols = incols;
575   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
576   PetscFunctionReturn(PETSC_SUCCESS);
577 }
578 
579 /*@
580   MatConjugate - replaces the matrix values with their complex conjugates
581 
582   Logically Collective
583 
584   Input Parameter:
585 . mat - the matrix
586 
587   Level: advanced
588 
589 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
590 @*/
591 PetscErrorCode MatConjugate(Mat mat)
592 {
593   PetscFunctionBegin;
594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
596   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
597     PetscUseTypeMethod(mat, conjugate);
598     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
599   }
600   PetscFunctionReturn(PETSC_SUCCESS);
601 }
602 
603 /*@C
604   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
605 
606   Not Collective
607 
608   Input Parameters:
609 + mat   - the matrix
610 . row   - the row to get
611 . ncols - the number of nonzeros
612 . cols  - the columns of the nonzeros
613 - vals  - if nonzero the column values
614 
615   Level: advanced
616 
617   Notes:
618   This routine should be called after you have finished examining the entries.
619 
620   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
621   us of the array after it has been restored. If you pass `NULL`, it will
622   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
623 
624   Fortran Notes:
625   The calling sequence is
626 .vb
627    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
628       Mat     matrix (input)
629       integer row    (input)
630       integer ncols  (output)
631       integer cols(maxcols) (output)
632       double precision (or double complex) values(maxcols) output
633 .ve
634   Where maxcols >= maximum nonzeros in any row of the matrix.
635 
636   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
637   before another call to `MatGetRow()` can be made.
638 
639 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
640 @*/
641 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
642 {
643   PetscFunctionBegin;
644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
645   if (ncols) PetscAssertPointer(ncols, 3);
646   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
647   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
648   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
649   if (ncols) *ncols = 0;
650   if (cols) *cols = NULL;
651   if (vals) *vals = NULL;
652   PetscFunctionReturn(PETSC_SUCCESS);
653 }
654 
655 /*@
656   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
657   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
658 
659   Not Collective
660 
661   Input Parameter:
662 . mat - the matrix
663 
664   Level: advanced
665 
666   Note:
667   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.
668 
669 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
670 @*/
671 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
672 {
673   PetscFunctionBegin;
674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
675   PetscValidType(mat, 1);
676   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
677   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
678   MatCheckPreallocated(mat, 1);
679   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
680   PetscUseTypeMethod(mat, getrowuppertriangular);
681   PetscFunctionReturn(PETSC_SUCCESS);
682 }
683 
684 /*@
685   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
686 
687   Not Collective
688 
689   Input Parameter:
690 . mat - the matrix
691 
692   Level: advanced
693 
694   Note:
695   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
696 
697 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
698 @*/
699 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
700 {
701   PetscFunctionBegin;
702   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
703   PetscValidType(mat, 1);
704   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
705   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
706   MatCheckPreallocated(mat, 1);
707   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
708   PetscUseTypeMethod(mat, restorerowuppertriangular);
709   PetscFunctionReturn(PETSC_SUCCESS);
710 }
711 
712 /*@C
713   MatSetOptionsPrefix - Sets the prefix used for searching for all
714   `Mat` options in the database.
715 
716   Logically Collective
717 
718   Input Parameters:
719 + A      - the matrix
720 - prefix - the prefix to prepend to all option names
721 
722   Level: advanced
723 
724   Notes:
725   A hyphen (-) must NOT be given at the beginning of the prefix name.
726   The first character of all runtime options is AUTOMATICALLY the hyphen.
727 
728   This is NOT used for options for the factorization of the matrix. Normally the
729   prefix is automatically passed in from the PC calling the factorization. To set
730   it directly use  `MatSetOptionsPrefixFactor()`
731 
732 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
733 @*/
734 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
735 {
736   PetscFunctionBegin;
737   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
738   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
739   PetscFunctionReturn(PETSC_SUCCESS);
740 }
741 
742 /*@C
743   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
744   for matrices created with `MatGetFactor()`
745 
746   Logically Collective
747 
748   Input Parameters:
749 + A      - the matrix
750 - prefix - the prefix to prepend to all option names for the factored matrix
751 
752   Level: developer
753 
754   Notes:
755   A hyphen (-) must NOT be given at the beginning of the prefix name.
756   The first character of all runtime options is AUTOMATICALLY the hyphen.
757 
758   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
759   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
760 
761 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
762 @*/
763 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
764 {
765   PetscFunctionBegin;
766   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
767   if (prefix) {
768     PetscAssertPointer(prefix, 2);
769     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
770     if (prefix != A->factorprefix) {
771       PetscCall(PetscFree(A->factorprefix));
772       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
773     }
774   } else PetscCall(PetscFree(A->factorprefix));
775   PetscFunctionReturn(PETSC_SUCCESS);
776 }
777 
778 /*@C
779   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
780   for matrices created with `MatGetFactor()`
781 
782   Logically Collective
783 
784   Input Parameters:
785 + A      - the matrix
786 - prefix - the prefix to prepend to all option names for the factored matrix
787 
788   Level: developer
789 
790   Notes:
791   A hyphen (-) must NOT be given at the beginning of the prefix name.
792   The first character of all runtime options is AUTOMATICALLY the hyphen.
793 
794   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
795   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
796 
797 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
798           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
799           `MatSetOptionsPrefix()`
800 @*/
801 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
802 {
803   size_t len1, len2, new_len;
804 
805   PetscFunctionBegin;
806   PetscValidHeader(A, 1);
807   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
808   if (!A->factorprefix) {
809     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
810     PetscFunctionReturn(PETSC_SUCCESS);
811   }
812   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
813 
814   PetscCall(PetscStrlen(A->factorprefix, &len1));
815   PetscCall(PetscStrlen(prefix, &len2));
816   new_len = len1 + len2 + 1;
817   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
818   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
819   PetscFunctionReturn(PETSC_SUCCESS);
820 }
821 
822 /*@C
823   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
824   matrix options in the database.
825 
826   Logically Collective
827 
828   Input Parameters:
829 + A      - the matrix
830 - prefix - the prefix to prepend to all option names
831 
832   Level: advanced
833 
834   Note:
835   A hyphen (-) must NOT be given at the beginning of the prefix name.
836   The first character of all runtime options is AUTOMATICALLY the hyphen.
837 
838 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
839 @*/
840 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
841 {
842   PetscFunctionBegin;
843   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
844   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
845   PetscFunctionReturn(PETSC_SUCCESS);
846 }
847 
848 /*@C
849   MatGetOptionsPrefix - Gets the prefix used for searching for all
850   matrix options in the database.
851 
852   Not Collective
853 
854   Input Parameter:
855 . A - the matrix
856 
857   Output Parameter:
858 . prefix - pointer to the prefix string used
859 
860   Level: advanced
861 
862   Fortran Note:
863   The user should pass in a string `prefix` of
864   sufficient length to hold the prefix.
865 
866 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
867 @*/
868 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
869 {
870   PetscFunctionBegin;
871   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
872   PetscAssertPointer(prefix, 2);
873   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
874   PetscFunctionReturn(PETSC_SUCCESS);
875 }
876 
877 /*@
878   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by the user.
879 
880   Collective
881 
882   Input Parameter:
883 . A - the matrix
884 
885   Level: beginner
886 
887   Notes:
888   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
889 
890   Users can reset the preallocation to access the original memory.
891 
892   Currently only supported for  `MATAIJ` matrices.
893 
894 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
895 @*/
896 PetscErrorCode MatResetPreallocation(Mat A)
897 {
898   PetscFunctionBegin;
899   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
900   PetscValidType(A, 1);
901   PetscCheck(A->insertmode == NOT_SET_VALUES, PETSC_COMM_SELF, PETSC_ERR_SUP, "Cannot reset preallocation after setting some values but not yet calling MatAssemblyBegin()/MatAsssemblyEnd()");
902   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
903   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
904   PetscFunctionReturn(PETSC_SUCCESS);
905 }
906 
907 /*@
908   MatSetUp - Sets up the internal matrix data structures for later use.
909 
910   Collective
911 
912   Input Parameter:
913 . A - the matrix
914 
915   Level: intermediate
916 
917   Notes:
918   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
919   setting values in the matrix.
920 
921   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
922 
923 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
924 @*/
925 PetscErrorCode MatSetUp(Mat A)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
929   if (!((PetscObject)A)->type_name) {
930     PetscMPIInt size;
931 
932     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
933     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
934   }
935   if (!A->preallocated) PetscTryTypeMethod(A, setup);
936   PetscCall(PetscLayoutSetUp(A->rmap));
937   PetscCall(PetscLayoutSetUp(A->cmap));
938   A->preallocated = PETSC_TRUE;
939   PetscFunctionReturn(PETSC_SUCCESS);
940 }
941 
942 #if defined(PETSC_HAVE_SAWS)
943   #include <petscviewersaws.h>
944 #endif
945 
946 /*
947    If threadsafety is on extraneous matrices may be printed
948 
949    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
950 */
951 #if !defined(PETSC_HAVE_THREADSAFETY)
952 static PetscInt insidematview = 0;
953 #endif
954 
955 /*@C
956   MatViewFromOptions - View properties of the matrix based on options set in the options database
957 
958   Collective
959 
960   Input Parameters:
961 + A    - the matrix
962 . obj  - optional additional object that provides the options prefix to use
963 - name - command line option
964 
965   Options Database Key:
966 . -mat_view [viewertype]:... - the viewer and its options
967 
968   Level: intermediate
969 
970   Note:
971 .vb
972     If no value is provided ascii:stdout is used
973        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
974                                                   for example ascii::ascii_info prints just the information about the object not all details
975                                                   unless :append is given filename opens in write mode, overwriting what was already there
976        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
977        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
978        socket[:port]                             defaults to the standard output port
979        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
980 .ve
981 
982 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
983 @*/
984 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
985 {
986   PetscFunctionBegin;
987   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
988 #if !defined(PETSC_HAVE_THREADSAFETY)
989   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
990 #endif
991   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
992   PetscFunctionReturn(PETSC_SUCCESS);
993 }
994 
995 /*@C
996   MatView - display information about a matrix in a variety ways
997 
998   Collective
999 
1000   Input Parameters:
1001 + mat    - the matrix
1002 - viewer - visualization context
1003 
1004   Options Database Keys:
1005 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1006 . -mat_view ::ascii_info_detail    - Prints more detailed info
1007 . -mat_view                        - Prints matrix in ASCII format
1008 . -mat_view ::ascii_matlab         - Prints matrix in MATLAB format
1009 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1010 . -display <name>                  - Sets display name (default is host)
1011 . -draw_pause <sec>                - Sets number of seconds to pause after display
1012 . -mat_view socket                 - Sends matrix to socket, can be accessed from MATLAB (see Users-Manual: ch_matlab for details)
1013 . -viewer_socket_machine <machine> - -
1014 . -viewer_socket_port <port>       - -
1015 . -mat_view binary                 - save matrix to file in binary format
1016 - -viewer_binary_filename <name>   - -
1017 
1018   Level: beginner
1019 
1020   Notes:
1021   The available visualization contexts include
1022 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1023 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1024 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1025 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1026 
1027   The user can open alternative visualization contexts with
1028 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1029 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1030   specified file; corresponding input uses `MatLoad()`
1031 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1032   an X window display
1033 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1034   Currently only the `MATSEQDENSE` and `MATAIJ`
1035   matrix types support the Socket viewer.
1036 
1037   The user can call `PetscViewerPushFormat()` to specify the output
1038   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1039   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1040 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1041 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in MATLAB format
1042 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1043 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1044   format common among all matrix types
1045 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1046   format (which is in many cases the same as the default)
1047 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1048   size and structure (not the matrix entries)
1049 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1050   the matrix structure
1051 
1052   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1053   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1054 
1055   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1056 
1057   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1058   viewer is used.
1059 
1060   See share/petsc/matlab/PetscBinaryRead.m for a MATLAB code that can read in the binary file when the binary
1061   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1062 
1063   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1064   and then use the following mouse functions.
1065 .vb
1066   left mouse: zoom in
1067   middle mouse: zoom out
1068   right mouse: continue with the simulation
1069 .ve
1070 
1071 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1072           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1073 @*/
1074 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1075 {
1076   PetscInt          rows, cols, rbs, cbs;
1077   PetscBool         isascii, isstring, issaws;
1078   PetscViewerFormat format;
1079   PetscMPIInt       size;
1080 
1081   PetscFunctionBegin;
1082   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1083   PetscValidType(mat, 1);
1084   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1085   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1086   PetscCheckSameComm(mat, 1, viewer, 2);
1087 
1088   PetscCall(PetscViewerGetFormat(viewer, &format));
1089   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1090   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1091 
1092 #if !defined(PETSC_HAVE_THREADSAFETY)
1093   insidematview++;
1094 #endif
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1096   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1097   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1098   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1099 
1100   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1101   if (isascii) {
1102     if (!mat->preallocated) {
1103       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1104 #if !defined(PETSC_HAVE_THREADSAFETY)
1105       insidematview--;
1106 #endif
1107       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1108       PetscFunctionReturn(PETSC_SUCCESS);
1109     }
1110     if (!mat->assembled) {
1111       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1112 #if !defined(PETSC_HAVE_THREADSAFETY)
1113       insidematview--;
1114 #endif
1115       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1116       PetscFunctionReturn(PETSC_SUCCESS);
1117     }
1118     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1119     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1120       MatNullSpace nullsp, transnullsp;
1121 
1122       PetscCall(PetscViewerASCIIPushTab(viewer));
1123       PetscCall(MatGetSize(mat, &rows, &cols));
1124       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1125       if (rbs != 1 || cbs != 1) {
1126         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" : ""));
1127         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "%s\n", rows, cols, rbs, mat->bsizes ? " variable blocks set" : ""));
1128       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1129       if (mat->factortype) {
1130         MatSolverType solver;
1131         PetscCall(MatFactorGetSolverType(mat, &solver));
1132         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1133       }
1134       if (mat->ops->getinfo) {
1135         MatInfo info;
1136         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1137         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1138         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1139       }
1140       PetscCall(MatGetNullSpace(mat, &nullsp));
1141       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1142       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1143       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1144       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1145       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1146       PetscCall(PetscViewerASCIIPushTab(viewer));
1147       PetscCall(MatProductView(mat, viewer));
1148       PetscCall(PetscViewerASCIIPopTab(viewer));
1149       if (mat->bsizes && format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1150         IS tmp;
1151 
1152         PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), mat->nblocks, mat->bsizes, PETSC_USE_POINTER, &tmp));
1153         PetscCall(PetscObjectSetName((PetscObject)tmp, "Block Sizes"));
1154         PetscCall(PetscViewerASCIIPushTab(viewer));
1155         PetscCall(ISView(tmp, viewer));
1156         PetscCall(PetscViewerASCIIPopTab(viewer));
1157         PetscCall(ISDestroy(&tmp));
1158       }
1159     }
1160   } else if (issaws) {
1161 #if defined(PETSC_HAVE_SAWS)
1162     PetscMPIInt rank;
1163 
1164     PetscCall(PetscObjectName((PetscObject)mat));
1165     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1166     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1167 #endif
1168   } else if (isstring) {
1169     const char *type;
1170     PetscCall(MatGetType(mat, &type));
1171     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1172     PetscTryTypeMethod(mat, view, viewer);
1173   }
1174   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1175     PetscCall(PetscViewerASCIIPushTab(viewer));
1176     PetscUseTypeMethod(mat, viewnative, viewer);
1177     PetscCall(PetscViewerASCIIPopTab(viewer));
1178   } else if (mat->ops->view) {
1179     PetscCall(PetscViewerASCIIPushTab(viewer));
1180     PetscUseTypeMethod(mat, view, viewer);
1181     PetscCall(PetscViewerASCIIPopTab(viewer));
1182   }
1183   if (isascii) {
1184     PetscCall(PetscViewerGetFormat(viewer, &format));
1185     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1186   }
1187   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1188 #if !defined(PETSC_HAVE_THREADSAFETY)
1189   insidematview--;
1190 #endif
1191   PetscFunctionReturn(PETSC_SUCCESS);
1192 }
1193 
1194 #if defined(PETSC_USE_DEBUG)
1195   #include <../src/sys/totalview/tv_data_display.h>
1196 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1197 {
1198   TV_add_row("Local rows", "int", &mat->rmap->n);
1199   TV_add_row("Local columns", "int", &mat->cmap->n);
1200   TV_add_row("Global rows", "int", &mat->rmap->N);
1201   TV_add_row("Global columns", "int", &mat->cmap->N);
1202   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1203   return TV_format_OK;
1204 }
1205 #endif
1206 
1207 /*@C
1208   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1209   with `MatView()`.  The matrix format is determined from the options database.
1210   Generates a parallel MPI matrix if the communicator has more than one
1211   processor.  The default matrix type is `MATAIJ`.
1212 
1213   Collective
1214 
1215   Input Parameters:
1216 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1217             or some related function before a call to `MatLoad()`
1218 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1219 
1220   Options Database Key:
1221 . -matload_block_size <bs> - set block size
1222 
1223   Level: beginner
1224 
1225   Notes:
1226   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1227   `Mat` before calling this routine if you wish to set it from the options database.
1228 
1229   `MatLoad()` automatically loads into the options database any options
1230   given in the file filename.info where filename is the name of the file
1231   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1232   file will be ignored if you use the -viewer_binary_skip_info option.
1233 
1234   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1235   sets the default matrix type AIJ and sets the local and global sizes.
1236   If type and/or size is already set, then the same are used.
1237 
1238   In parallel, each processor can load a subset of rows (or the
1239   entire matrix).  This routine is especially useful when a large
1240   matrix is stored on disk and only part of it is desired on each
1241   processor.  For example, a parallel solver may access only some of
1242   the rows from each processor.  The algorithm used here reads
1243   relatively small blocks of data rather than reading the entire
1244   matrix and then subsetting it.
1245 
1246   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1247   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1248   or the sequence like
1249 .vb
1250     `PetscViewer` v;
1251     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1252     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1253     `PetscViewerSetFromOptions`(v);
1254     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1255     `PetscViewerFileSetName`(v,"datafile");
1256 .ve
1257   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1258 $ -viewer_type {binary, hdf5}
1259 
1260   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1261   and src/mat/tutorials/ex10.c with the second approach.
1262 
1263   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1264   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1265   Multiple objects, both matrices and vectors, can be stored within the same file.
1266   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1267 
1268   Most users should not need to know the details of the binary storage
1269   format, since `MatLoad()` and `MatView()` completely hide these details.
1270   But for anyone who is interested, the standard binary matrix storage
1271   format is
1272 
1273 .vb
1274     PetscInt    MAT_FILE_CLASSID
1275     PetscInt    number of rows
1276     PetscInt    number of columns
1277     PetscInt    total number of nonzeros
1278     PetscInt    *number nonzeros in each row
1279     PetscInt    *column indices of all nonzeros (starting index is zero)
1280     PetscScalar *values of all nonzeros
1281 .ve
1282   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1283   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
1284   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1285 
1286   PETSc automatically does the byte swapping for
1287   machines that store the bytes reversed. Thus if you write your own binary
1288   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1289   and `PetscBinaryWrite()` to see how this may be done.
1290 
1291   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1292   Each processor's chunk is loaded independently by its owning MPI process.
1293   Multiple objects, both matrices and vectors, can be stored within the same file.
1294   They are looked up by their PetscObject name.
1295 
1296   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1297   by default the same structure and naming of the AIJ arrays and column count
1298   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1299 $    save example.mat A b -v7.3
1300   can be directly read by this routine (see Reference 1 for details).
1301 
1302   Depending on your MATLAB version, this format might be a default,
1303   otherwise you can set it as default in Preferences.
1304 
1305   Unless -nocompression flag is used to save the file in MATLAB,
1306   PETSc must be configured with ZLIB package.
1307 
1308   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1309 
1310   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1311 
1312   Corresponding `MatView()` is not yet implemented.
1313 
1314   The loaded matrix is actually a transpose of the original one in MATLAB,
1315   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1316   With this format, matrix is automatically transposed by PETSc,
1317   unless the matrix is marked as SPD or symmetric
1318   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1319 
1320   See MATLAB Documentation on `save()`, <https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version>
1321 
1322 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1323  @*/
1324 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1325 {
1326   PetscBool flg;
1327 
1328   PetscFunctionBegin;
1329   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1330   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1331 
1332   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1333 
1334   flg = PETSC_FALSE;
1335   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1336   if (flg) {
1337     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1338     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1339   }
1340   flg = PETSC_FALSE;
1341   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1342   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1343 
1344   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1345   PetscUseTypeMethod(mat, load, viewer);
1346   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1347   PetscFunctionReturn(PETSC_SUCCESS);
1348 }
1349 
1350 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1351 {
1352   Mat_Redundant *redund = *redundant;
1353 
1354   PetscFunctionBegin;
1355   if (redund) {
1356     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1357       PetscCall(ISDestroy(&redund->isrow));
1358       PetscCall(ISDestroy(&redund->iscol));
1359       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1360     } else {
1361       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1362       PetscCall(PetscFree(redund->sbuf_j));
1363       PetscCall(PetscFree(redund->sbuf_a));
1364       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1365         PetscCall(PetscFree(redund->rbuf_j[i]));
1366         PetscCall(PetscFree(redund->rbuf_a[i]));
1367       }
1368       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1369     }
1370 
1371     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1372     PetscCall(PetscFree(redund));
1373   }
1374   PetscFunctionReturn(PETSC_SUCCESS);
1375 }
1376 
1377 /*@C
1378   MatDestroy - Frees space taken by a matrix.
1379 
1380   Collective
1381 
1382   Input Parameter:
1383 . A - the matrix
1384 
1385   Level: beginner
1386 
1387   Developer Note:
1388   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1389   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1390   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1391   if changes are needed here.
1392 
1393 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1394 @*/
1395 PetscErrorCode MatDestroy(Mat *A)
1396 {
1397   PetscFunctionBegin;
1398   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1399   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1400   if (--((PetscObject)(*A))->refct > 0) {
1401     *A = NULL;
1402     PetscFunctionReturn(PETSC_SUCCESS);
1403   }
1404 
1405   /* if memory was published with SAWs then destroy it */
1406   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1407   PetscTryTypeMethod(*A, destroy);
1408 
1409   PetscCall(PetscFree((*A)->factorprefix));
1410   PetscCall(PetscFree((*A)->defaultvectype));
1411   PetscCall(PetscFree((*A)->defaultrandtype));
1412   PetscCall(PetscFree((*A)->bsizes));
1413   PetscCall(PetscFree((*A)->solvertype));
1414   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1415   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1416   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1417   PetscCall(MatProductClear(*A));
1418   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1419   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1420   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1421   PetscCall(MatDestroy(&(*A)->schur));
1422   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1423   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1424   PetscCall(PetscHeaderDestroy(A));
1425   PetscFunctionReturn(PETSC_SUCCESS);
1426 }
1427 
1428 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1429 /*@C
1430   MatSetValues - Inserts or adds a block of values into a matrix.
1431   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1432   MUST be called after all calls to `MatSetValues()` have been completed.
1433 
1434   Not Collective
1435 
1436   Input Parameters:
1437 + mat  - the matrix
1438 . v    - a logically two-dimensional array of values
1439 . m    - the number of rows
1440 . idxm - the global indices of the rows
1441 . n    - the number of columns
1442 . idxn - the global indices of the columns
1443 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1444 
1445   Level: beginner
1446 
1447   Notes:
1448   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1449 
1450   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1451   options cannot be mixed without intervening calls to the assembly
1452   routines.
1453 
1454   `MatSetValues()` uses 0-based row and column numbers in Fortran
1455   as well as in C.
1456 
1457   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1458   simply ignored. This allows easily inserting element stiffness matrices
1459   with homogeneous Dirichlet boundary conditions that you don't want represented
1460   in the matrix.
1461 
1462   Efficiency Alert:
1463   The routine `MatSetValuesBlocked()` may offer much better efficiency
1464   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1465 
1466   Developer Note:
1467   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1468   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1469 
1470 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1471           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1472 @*/
1473 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1474 {
1475   PetscFunctionBeginHot;
1476   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1477   PetscValidType(mat, 1);
1478   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1479   PetscAssertPointer(idxm, 3);
1480   PetscAssertPointer(idxn, 5);
1481   MatCheckPreallocated(mat, 1);
1482 
1483   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1484   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1485 
1486   if (PetscDefined(USE_DEBUG)) {
1487     PetscInt i, j;
1488 
1489     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1490     for (i = 0; i < m; i++) {
1491       for (j = 0; j < n; j++) {
1492         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1493 #if defined(PETSC_USE_COMPLEX)
1494           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]);
1495 #else
1496           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]);
1497 #endif
1498       }
1499     }
1500     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);
1501     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);
1502   }
1503 
1504   if (mat->assembled) {
1505     mat->was_assembled = PETSC_TRUE;
1506     mat->assembled     = PETSC_FALSE;
1507   }
1508   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1509   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1510   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1511   PetscFunctionReturn(PETSC_SUCCESS);
1512 }
1513 
1514 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1515 /*@C
1516   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1517   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1518   MUST be called after all calls to `MatSetValues()` have been completed.
1519 
1520   Not Collective
1521 
1522   Input Parameters:
1523 + mat  - the matrix
1524 . v    - a logically two-dimensional array of values
1525 . ism  - the rows to provide
1526 . isn  - the columns to provide
1527 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1528 
1529   Level: beginner
1530 
1531   Notes:
1532   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1533 
1534   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1535   options cannot be mixed without intervening calls to the assembly
1536   routines.
1537 
1538   `MatSetValues()` uses 0-based row and column numbers in Fortran
1539   as well as in C.
1540 
1541   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1542   simply ignored. This allows easily inserting element stiffness matrices
1543   with homogeneous Dirichlet boundary conditions that you don't want represented
1544   in the matrix.
1545 
1546   Efficiency Alert:
1547   The routine `MatSetValuesBlocked()` may offer much better efficiency
1548   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1549 
1550   This is currently not optimized for any particular `ISType`
1551 
1552   Developer Note:
1553   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1554   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1555 
1556 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1557           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1558 @*/
1559 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1560 {
1561   PetscInt        m, n;
1562   const PetscInt *rows, *cols;
1563 
1564   PetscFunctionBeginHot;
1565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1566   PetscCall(ISGetIndices(ism, &rows));
1567   PetscCall(ISGetIndices(isn, &cols));
1568   PetscCall(ISGetLocalSize(ism, &m));
1569   PetscCall(ISGetLocalSize(isn, &n));
1570   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1571   PetscCall(ISRestoreIndices(ism, &rows));
1572   PetscCall(ISRestoreIndices(isn, &cols));
1573   PetscFunctionReturn(PETSC_SUCCESS);
1574 }
1575 
1576 /*@
1577   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1578   values into a matrix
1579 
1580   Not Collective
1581 
1582   Input Parameters:
1583 + mat - the matrix
1584 . row - the (block) row to set
1585 - v   - a logically two-dimensional array of values
1586 
1587   Level: intermediate
1588 
1589   Notes:
1590   The values, `v`, are column-oriented (for the block version) and sorted
1591 
1592   All the nonzero values in `row` must be provided
1593 
1594   The matrix must have previously had its column indices set, likely by having been assembled.
1595 
1596   `row` must belong to this MPI process
1597 
1598 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1599           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1600 @*/
1601 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1602 {
1603   PetscInt globalrow;
1604 
1605   PetscFunctionBegin;
1606   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1607   PetscValidType(mat, 1);
1608   PetscAssertPointer(v, 3);
1609   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1610   PetscCall(MatSetValuesRow(mat, globalrow, v));
1611   PetscFunctionReturn(PETSC_SUCCESS);
1612 }
1613 
1614 /*@
1615   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1616   values into a matrix
1617 
1618   Not Collective
1619 
1620   Input Parameters:
1621 + mat - the matrix
1622 . row - the (block) row to set
1623 - 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
1624 
1625   Level: advanced
1626 
1627   Notes:
1628   The values, `v`, are column-oriented for the block version.
1629 
1630   All the nonzeros in `row` must be provided
1631 
1632   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1633 
1634   `row` must belong to this process
1635 
1636 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1637           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1638 @*/
1639 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1640 {
1641   PetscFunctionBeginHot;
1642   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1643   PetscValidType(mat, 1);
1644   MatCheckPreallocated(mat, 1);
1645   PetscAssertPointer(v, 3);
1646   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1647   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1648   mat->insertmode = INSERT_VALUES;
1649 
1650   if (mat->assembled) {
1651     mat->was_assembled = PETSC_TRUE;
1652     mat->assembled     = PETSC_FALSE;
1653   }
1654   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1655   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1656   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1657   PetscFunctionReturn(PETSC_SUCCESS);
1658 }
1659 
1660 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
1661 /*@
1662   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1663   Using structured grid indexing
1664 
1665   Not Collective
1666 
1667   Input Parameters:
1668 + mat  - the matrix
1669 . m    - number of rows being entered
1670 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1671 . n    - number of columns being entered
1672 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1673 . v    - a logically two-dimensional array of values
1674 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1675 
1676   Level: beginner
1677 
1678   Notes:
1679   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1680 
1681   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1682   options cannot be mixed without intervening calls to the assembly
1683   routines.
1684 
1685   The grid coordinates are across the entire grid, not just the local portion
1686 
1687   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1688   as well as in C.
1689 
1690   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1691 
1692   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1693   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1694 
1695   The columns and rows in the stencil passed in MUST be contained within the
1696   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1697   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1698   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1699   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1700 
1701   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1702   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1703   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1704   `DM_BOUNDARY_PERIODIC` boundary type.
1705 
1706   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
1707   a single value per point) you can skip filling those indices.
1708 
1709   Inspired by the structured grid interface to the HYPRE package
1710   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1711 
1712   Efficiency Alert:
1713   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1714   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1715 
1716   Fortran Note:
1717   `idxm` and `idxn` should be declared as
1718 $     MatStencil idxm(4,m),idxn(4,n)
1719   and the values inserted using
1720 .vb
1721     idxm(MatStencil_i,1) = i
1722     idxm(MatStencil_j,1) = j
1723     idxm(MatStencil_k,1) = k
1724     idxm(MatStencil_c,1) = c
1725     etc
1726 .ve
1727 
1728 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1729           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1730 @*/
1731 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1732 {
1733   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1734   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1735   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1736 
1737   PetscFunctionBegin;
1738   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1739   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1740   PetscValidType(mat, 1);
1741   PetscAssertPointer(idxm, 3);
1742   PetscAssertPointer(idxn, 5);
1743 
1744   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1745     jdxm = buf;
1746     jdxn = buf + m;
1747   } else {
1748     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1749     jdxm = bufm;
1750     jdxn = bufn;
1751   }
1752   for (i = 0; i < m; i++) {
1753     for (j = 0; j < 3 - sdim; j++) dxm++;
1754     tmp = *dxm++ - starts[0];
1755     for (j = 0; j < dim - 1; j++) {
1756       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1757       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1758     }
1759     if (mat->stencil.noc) dxm++;
1760     jdxm[i] = tmp;
1761   }
1762   for (i = 0; i < n; i++) {
1763     for (j = 0; j < 3 - sdim; j++) dxn++;
1764     tmp = *dxn++ - starts[0];
1765     for (j = 0; j < dim - 1; j++) {
1766       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1767       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1768     }
1769     if (mat->stencil.noc) dxn++;
1770     jdxn[i] = tmp;
1771   }
1772   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1773   PetscCall(PetscFree2(bufm, bufn));
1774   PetscFunctionReturn(PETSC_SUCCESS);
1775 }
1776 
1777 /*@
1778   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1779   Using structured grid indexing
1780 
1781   Not Collective
1782 
1783   Input Parameters:
1784 + mat  - the matrix
1785 . m    - number of rows being entered
1786 . idxm - grid coordinates for matrix rows being entered
1787 . n    - number of columns being entered
1788 . idxn - grid coordinates for matrix columns being entered
1789 . v    - a logically two-dimensional array of values
1790 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1791 
1792   Level: beginner
1793 
1794   Notes:
1795   By default the values, `v`, are row-oriented and unsorted.
1796   See `MatSetOption()` for other options.
1797 
1798   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1799   options cannot be mixed without intervening calls to the assembly
1800   routines.
1801 
1802   The grid coordinates are across the entire grid, not just the local portion
1803 
1804   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1805   as well as in C.
1806 
1807   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1808 
1809   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1810   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1811 
1812   The columns and rows in the stencil passed in MUST be contained within the
1813   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1814   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1815   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1816   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1817 
1818   Negative indices may be passed in idxm and idxn, these rows and columns are
1819   simply ignored. This allows easily inserting element stiffness matrices
1820   with homogeneous Dirichlet boundary conditions that you don't want represented
1821   in the matrix.
1822 
1823   Inspired by the structured grid interface to the HYPRE package
1824   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1825 
1826   Fortran Note:
1827   `idxm` and `idxn` should be declared as
1828 $     MatStencil idxm(4,m),idxn(4,n)
1829   and the values inserted using
1830 .vb
1831     idxm(MatStencil_i,1) = i
1832     idxm(MatStencil_j,1) = j
1833     idxm(MatStencil_k,1) = k
1834    etc
1835 .ve
1836 
1837 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1838           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1839           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1840 @*/
1841 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1842 {
1843   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1844   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1845   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1846 
1847   PetscFunctionBegin;
1848   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1849   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1850   PetscValidType(mat, 1);
1851   PetscAssertPointer(idxm, 3);
1852   PetscAssertPointer(idxn, 5);
1853   PetscAssertPointer(v, 6);
1854 
1855   if ((m + n) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
1856     jdxm = buf;
1857     jdxn = buf + m;
1858   } else {
1859     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1860     jdxm = bufm;
1861     jdxn = bufn;
1862   }
1863   for (i = 0; i < m; i++) {
1864     for (j = 0; j < 3 - sdim; j++) dxm++;
1865     tmp = *dxm++ - starts[0];
1866     for (j = 0; j < sdim - 1; j++) {
1867       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1868       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1869     }
1870     dxm++;
1871     jdxm[i] = tmp;
1872   }
1873   for (i = 0; i < n; i++) {
1874     for (j = 0; j < 3 - sdim; j++) dxn++;
1875     tmp = *dxn++ - starts[0];
1876     for (j = 0; j < sdim - 1; j++) {
1877       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1878       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1879     }
1880     dxn++;
1881     jdxn[i] = tmp;
1882   }
1883   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1884   PetscCall(PetscFree2(bufm, bufn));
1885   PetscFunctionReturn(PETSC_SUCCESS);
1886 }
1887 
1888 /*@
1889   MatSetStencil - Sets the grid information for setting values into a matrix via
1890   `MatSetValuesStencil()`
1891 
1892   Not Collective
1893 
1894   Input Parameters:
1895 + mat    - the matrix
1896 . dim    - dimension of the grid 1, 2, or 3
1897 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1898 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1899 - dof    - number of degrees of freedom per node
1900 
1901   Level: beginner
1902 
1903   Notes:
1904   Inspired by the structured grid interface to the HYPRE package
1905   (www.llnl.gov/CASC/hyper)
1906 
1907   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1908   user.
1909 
1910 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1911           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1912 @*/
1913 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1914 {
1915   PetscFunctionBegin;
1916   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1917   PetscAssertPointer(dims, 3);
1918   PetscAssertPointer(starts, 4);
1919 
1920   mat->stencil.dim = dim + (dof > 1);
1921   for (PetscInt i = 0; i < dim; i++) {
1922     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1923     mat->stencil.starts[i] = starts[dim - i - 1];
1924   }
1925   mat->stencil.dims[dim]   = dof;
1926   mat->stencil.starts[dim] = 0;
1927   mat->stencil.noc         = (PetscBool)(dof == 1);
1928   PetscFunctionReturn(PETSC_SUCCESS);
1929 }
1930 
1931 /*@C
1932   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1933 
1934   Not Collective
1935 
1936   Input Parameters:
1937 + mat  - the matrix
1938 . v    - a logically two-dimensional array of values
1939 . m    - the number of block rows
1940 . idxm - the global block indices
1941 . n    - the number of block columns
1942 . idxn - the global block indices
1943 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1944 
1945   Level: intermediate
1946 
1947   Notes:
1948   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1949   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1950 
1951   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1952   NOT the total number of rows/columns; for example, if the block size is 2 and
1953   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1954   The values in idxm would be 1 2; that is the first index for each block divided by
1955   the block size.
1956 
1957   You must call `MatSetBlockSize()` when constructing this matrix (before
1958   preallocating it).
1959 
1960   By default the values, `v`, are row-oriented, so the layout of
1961   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1962 
1963   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1964   options cannot be mixed without intervening calls to the assembly
1965   routines.
1966 
1967   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1968   as well as in C.
1969 
1970   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1971   simply ignored. This allows easily inserting element stiffness matrices
1972   with homogeneous Dirichlet boundary conditions that you don't want represented
1973   in the matrix.
1974 
1975   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1976   internal searching must be done to determine where to place the
1977   data in the matrix storage space.  By instead inserting blocks of
1978   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1979   reduced.
1980 
1981   Example:
1982 .vb
1983    Suppose m=n=2 and block size(bs) = 2 The array is
1984 
1985    1  2  | 3  4
1986    5  6  | 7  8
1987    - - - | - - -
1988    9  10 | 11 12
1989    13 14 | 15 16
1990 
1991    v[] should be passed in like
1992    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1993 
1994   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1995    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1996 .ve
1997 
1998 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1999 @*/
2000 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
2001 {
2002   PetscFunctionBeginHot;
2003   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2004   PetscValidType(mat, 1);
2005   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2006   PetscAssertPointer(idxm, 3);
2007   PetscAssertPointer(idxn, 5);
2008   MatCheckPreallocated(mat, 1);
2009   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2010   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2011   if (PetscDefined(USE_DEBUG)) {
2012     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2013     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2014   }
2015   if (PetscDefined(USE_DEBUG)) {
2016     PetscInt rbs, cbs, M, N, i;
2017     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2018     PetscCall(MatGetSize(mat, &M, &N));
2019     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
2020     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
2021   }
2022   if (mat->assembled) {
2023     mat->was_assembled = PETSC_TRUE;
2024     mat->assembled     = PETSC_FALSE;
2025   }
2026   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2027   if (mat->ops->setvaluesblocked) {
2028     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2029   } else {
2030     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2031     PetscInt i, j, bs, cbs;
2032 
2033     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2034     if ((m * bs + n * cbs) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2035       iidxm = buf;
2036       iidxn = buf + m * bs;
2037     } else {
2038       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2039       iidxm = bufr;
2040       iidxn = bufc;
2041     }
2042     for (i = 0; i < m; i++) {
2043       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2044     }
2045     if (m != n || bs != cbs || idxm != idxn) {
2046       for (i = 0; i < n; i++) {
2047         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2048       }
2049     } else iidxn = iidxm;
2050     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2051     PetscCall(PetscFree2(bufr, bufc));
2052   }
2053   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2054   PetscFunctionReturn(PETSC_SUCCESS);
2055 }
2056 
2057 /*@C
2058   MatGetValues - Gets a block of local values from a matrix.
2059 
2060   Not Collective; can only return values that are owned by the give process
2061 
2062   Input Parameters:
2063 + mat  - the matrix
2064 . v    - a logically two-dimensional array for storing the values
2065 . m    - the number of rows
2066 . idxm - the  global indices of the rows
2067 . n    - the number of columns
2068 - idxn - the global indices of the columns
2069 
2070   Level: advanced
2071 
2072   Notes:
2073   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2074   The values, `v`, are then returned in a row-oriented format,
2075   analogous to that used by default in `MatSetValues()`.
2076 
2077   `MatGetValues()` uses 0-based row and column numbers in
2078   Fortran as well as in C.
2079 
2080   `MatGetValues()` requires that the matrix has been assembled
2081   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2082   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2083   without intermediate matrix assembly.
2084 
2085   Negative row or column indices will be ignored and those locations in `v` will be
2086   left unchanged.
2087 
2088   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2089   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2090   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2091 
2092 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2093 @*/
2094 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2095 {
2096   PetscFunctionBegin;
2097   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2098   PetscValidType(mat, 1);
2099   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2100   PetscAssertPointer(idxm, 3);
2101   PetscAssertPointer(idxn, 5);
2102   PetscAssertPointer(v, 6);
2103   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2104   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2105   MatCheckPreallocated(mat, 1);
2106 
2107   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2108   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2109   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2110   PetscFunctionReturn(PETSC_SUCCESS);
2111 }
2112 
2113 /*@C
2114   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2115   defined previously by `MatSetLocalToGlobalMapping()`
2116 
2117   Not Collective
2118 
2119   Input Parameters:
2120 + mat  - the matrix
2121 . nrow - number of rows
2122 . irow - the row local indices
2123 . ncol - number of columns
2124 - icol - the column local indices
2125 
2126   Output Parameter:
2127 . y - a logically two-dimensional array of values
2128 
2129   Level: advanced
2130 
2131   Notes:
2132   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2133 
2134   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,
2135   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2136   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2137   with `MatSetLocalToGlobalMapping()`.
2138 
2139   Developer Note:
2140   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2141   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2142 
2143 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2144           `MatSetValuesLocal()`, `MatGetValues()`
2145 @*/
2146 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2147 {
2148   PetscFunctionBeginHot;
2149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2150   PetscValidType(mat, 1);
2151   MatCheckPreallocated(mat, 1);
2152   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2153   PetscAssertPointer(irow, 3);
2154   PetscAssertPointer(icol, 5);
2155   if (PetscDefined(USE_DEBUG)) {
2156     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2157     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2158   }
2159   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2160   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2161   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2162   else {
2163     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2164     if ((nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2165       irowm = buf;
2166       icolm = buf + nrow;
2167     } else {
2168       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2169       irowm = bufr;
2170       icolm = bufc;
2171     }
2172     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2173     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2174     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2175     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2176     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2177     PetscCall(PetscFree2(bufr, bufc));
2178   }
2179   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2180   PetscFunctionReturn(PETSC_SUCCESS);
2181 }
2182 
2183 /*@
2184   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2185   the same size. Currently, this can only be called once and creates the given matrix.
2186 
2187   Not Collective
2188 
2189   Input Parameters:
2190 + mat  - the matrix
2191 . nb   - the number of blocks
2192 . bs   - the number of rows (and columns) in each block
2193 . rows - a concatenation of the rows for each block
2194 - v    - a concatenation of logically two-dimensional arrays of values
2195 
2196   Level: advanced
2197 
2198   Notes:
2199   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2200 
2201   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2202 
2203 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2204           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2205 @*/
2206 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2207 {
2208   PetscFunctionBegin;
2209   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2210   PetscValidType(mat, 1);
2211   PetscAssertPointer(rows, 4);
2212   PetscAssertPointer(v, 5);
2213   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2214 
2215   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2216   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2217   else {
2218     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2219   }
2220   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2221   PetscFunctionReturn(PETSC_SUCCESS);
2222 }
2223 
2224 /*@
2225   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2226   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2227   using a local (per-processor) numbering.
2228 
2229   Not Collective
2230 
2231   Input Parameters:
2232 + x        - the matrix
2233 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2234 - cmapping - column mapping
2235 
2236   Level: intermediate
2237 
2238   Note:
2239   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2240 
2241 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2242 @*/
2243 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2244 {
2245   PetscFunctionBegin;
2246   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2247   PetscValidType(x, 1);
2248   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2249   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2250   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2251   else {
2252     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2253     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2254   }
2255   PetscFunctionReturn(PETSC_SUCCESS);
2256 }
2257 
2258 /*@
2259   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2260 
2261   Not Collective
2262 
2263   Input Parameter:
2264 . A - the matrix
2265 
2266   Output Parameters:
2267 + rmapping - row mapping
2268 - cmapping - column mapping
2269 
2270   Level: advanced
2271 
2272 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2273 @*/
2274 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2275 {
2276   PetscFunctionBegin;
2277   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2278   PetscValidType(A, 1);
2279   if (rmapping) {
2280     PetscAssertPointer(rmapping, 2);
2281     *rmapping = A->rmap->mapping;
2282   }
2283   if (cmapping) {
2284     PetscAssertPointer(cmapping, 3);
2285     *cmapping = A->cmap->mapping;
2286   }
2287   PetscFunctionReturn(PETSC_SUCCESS);
2288 }
2289 
2290 /*@
2291   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2292 
2293   Logically Collective
2294 
2295   Input Parameters:
2296 + A    - the matrix
2297 . rmap - row layout
2298 - cmap - column layout
2299 
2300   Level: advanced
2301 
2302   Note:
2303   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2304 
2305 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2306 @*/
2307 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2308 {
2309   PetscFunctionBegin;
2310   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2311   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2312   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2313   PetscFunctionReturn(PETSC_SUCCESS);
2314 }
2315 
2316 /*@
2317   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2318 
2319   Not Collective
2320 
2321   Input Parameter:
2322 . A - the matrix
2323 
2324   Output Parameters:
2325 + rmap - row layout
2326 - cmap - column layout
2327 
2328   Level: advanced
2329 
2330 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2331 @*/
2332 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2333 {
2334   PetscFunctionBegin;
2335   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2336   PetscValidType(A, 1);
2337   if (rmap) {
2338     PetscAssertPointer(rmap, 2);
2339     *rmap = A->rmap;
2340   }
2341   if (cmap) {
2342     PetscAssertPointer(cmap, 3);
2343     *cmap = A->cmap;
2344   }
2345   PetscFunctionReturn(PETSC_SUCCESS);
2346 }
2347 
2348 /*@C
2349   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2350   using a local numbering of the rows and columns.
2351 
2352   Not Collective
2353 
2354   Input Parameters:
2355 + mat  - the matrix
2356 . nrow - number of rows
2357 . irow - the row local indices
2358 . ncol - number of columns
2359 . icol - the column local indices
2360 . y    - a logically two-dimensional array of values
2361 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2362 
2363   Level: intermediate
2364 
2365   Notes:
2366   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2367 
2368   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2369   options cannot be mixed without intervening calls to the assembly
2370   routines.
2371 
2372   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2373   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2374 
2375   Developer Note:
2376   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2377   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2378 
2379 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2380           `MatGetValuesLocal()`
2381 @*/
2382 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2383 {
2384   PetscFunctionBeginHot;
2385   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2386   PetscValidType(mat, 1);
2387   MatCheckPreallocated(mat, 1);
2388   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2389   PetscAssertPointer(irow, 3);
2390   PetscAssertPointer(icol, 5);
2391   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2392   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2393   if (PetscDefined(USE_DEBUG)) {
2394     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2395     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2396   }
2397 
2398   if (mat->assembled) {
2399     mat->was_assembled = PETSC_TRUE;
2400     mat->assembled     = PETSC_FALSE;
2401   }
2402   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2403   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2404   else {
2405     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2406     const PetscInt *irowm, *icolm;
2407 
2408     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf)) {
2409       bufr  = buf;
2410       bufc  = buf + nrow;
2411       irowm = bufr;
2412       icolm = bufc;
2413     } else {
2414       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2415       irowm = bufr;
2416       icolm = bufc;
2417     }
2418     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2419     else irowm = irow;
2420     if (mat->cmap->mapping) {
2421       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2422         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2423       } else icolm = irowm;
2424     } else icolm = icol;
2425     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2426     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2427   }
2428   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2429   PetscFunctionReturn(PETSC_SUCCESS);
2430 }
2431 
2432 /*@C
2433   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2434   using a local ordering of the nodes a block at a time.
2435 
2436   Not Collective
2437 
2438   Input Parameters:
2439 + mat  - the matrix
2440 . nrow - number of rows
2441 . irow - the row local indices
2442 . ncol - number of columns
2443 . icol - the column local indices
2444 . y    - a logically two-dimensional array of values
2445 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2446 
2447   Level: intermediate
2448 
2449   Notes:
2450   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2451   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2452 
2453   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2454   options cannot be mixed without intervening calls to the assembly
2455   routines.
2456 
2457   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2458   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2459 
2460   Developer Note:
2461   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2462   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2463 
2464 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2465           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2466 @*/
2467 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2468 {
2469   PetscFunctionBeginHot;
2470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2471   PetscValidType(mat, 1);
2472   MatCheckPreallocated(mat, 1);
2473   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2474   PetscAssertPointer(irow, 3);
2475   PetscAssertPointer(icol, 5);
2476   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2477   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2478   if (PetscDefined(USE_DEBUG)) {
2479     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2480     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);
2481   }
2482 
2483   if (mat->assembled) {
2484     mat->was_assembled = PETSC_TRUE;
2485     mat->assembled     = PETSC_FALSE;
2486   }
2487   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2488     PetscInt irbs, rbs;
2489     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2490     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2491     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2492   }
2493   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2494     PetscInt icbs, cbs;
2495     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2496     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2497     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2498   }
2499   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2500   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2501   else {
2502     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2503     const PetscInt *irowm, *icolm;
2504 
2505     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= ((PetscInt)PETSC_STATIC_ARRAY_LENGTH(buf))) {
2506       bufr  = buf;
2507       bufc  = buf + nrow;
2508       irowm = bufr;
2509       icolm = bufc;
2510     } else {
2511       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2512       irowm = bufr;
2513       icolm = bufc;
2514     }
2515     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2516     else irowm = irow;
2517     if (mat->cmap->mapping) {
2518       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2519         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2520       } else icolm = irowm;
2521     } else icolm = icol;
2522     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2523     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2524   }
2525   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2526   PetscFunctionReturn(PETSC_SUCCESS);
2527 }
2528 
2529 /*@
2530   MatMultDiagonalBlock - Computes the matrix-vector product, $y = Dx$. Where `D` is defined by the inode or block structure of the diagonal
2531 
2532   Collective
2533 
2534   Input Parameters:
2535 + mat - the matrix
2536 - x   - the vector to be multiplied
2537 
2538   Output Parameter:
2539 . y - the result
2540 
2541   Level: developer
2542 
2543   Note:
2544   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2545   call `MatMultDiagonalBlock`(A,y,y).
2546 
2547 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2548 @*/
2549 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2550 {
2551   PetscFunctionBegin;
2552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2553   PetscValidType(mat, 1);
2554   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2555   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2556 
2557   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2558   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2559   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2560   MatCheckPreallocated(mat, 1);
2561 
2562   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2563   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2564   PetscFunctionReturn(PETSC_SUCCESS);
2565 }
2566 
2567 /*@
2568   MatMult - Computes the matrix-vector product, $y = Ax$.
2569 
2570   Neighbor-wise Collective
2571 
2572   Input Parameters:
2573 + mat - the matrix
2574 - x   - the vector to be multiplied
2575 
2576   Output Parameter:
2577 . y - the result
2578 
2579   Level: beginner
2580 
2581   Note:
2582   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2583   call `MatMult`(A,y,y).
2584 
2585 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2586 @*/
2587 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2588 {
2589   PetscFunctionBegin;
2590   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2591   PetscValidType(mat, 1);
2592   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2593   VecCheckAssembled(x);
2594   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2596   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2597   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2598   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);
2599   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);
2600   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);
2601   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);
2602   PetscCall(VecSetErrorIfLocked(y, 3));
2603   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2604   MatCheckPreallocated(mat, 1);
2605 
2606   PetscCall(VecLockReadPush(x));
2607   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2608   PetscUseTypeMethod(mat, mult, x, y);
2609   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2610   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2611   PetscCall(VecLockReadPop(x));
2612   PetscFunctionReturn(PETSC_SUCCESS);
2613 }
2614 
2615 /*@
2616   MatMultTranspose - Computes matrix transpose times a vector $y = A^T * x$.
2617 
2618   Neighbor-wise Collective
2619 
2620   Input Parameters:
2621 + mat - the matrix
2622 - x   - the vector to be multiplied
2623 
2624   Output Parameter:
2625 . y - the result
2626 
2627   Level: beginner
2628 
2629   Notes:
2630   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2631   call `MatMultTranspose`(A,y,y).
2632 
2633   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2634   use `MatMultHermitianTranspose()`
2635 
2636 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2637 @*/
2638 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2639 {
2640   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2641 
2642   PetscFunctionBegin;
2643   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2644   PetscValidType(mat, 1);
2645   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2646   VecCheckAssembled(x);
2647   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2648 
2649   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2650   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2651   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2652   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);
2653   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);
2654   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);
2655   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);
2656   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2657   MatCheckPreallocated(mat, 1);
2658 
2659   if (!mat->ops->multtranspose) {
2660     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2661     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);
2662   } else op = mat->ops->multtranspose;
2663   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2664   PetscCall(VecLockReadPush(x));
2665   PetscCall((*op)(mat, x, y));
2666   PetscCall(VecLockReadPop(x));
2667   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2668   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2669   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2670   PetscFunctionReturn(PETSC_SUCCESS);
2671 }
2672 
2673 /*@
2674   MatMultHermitianTranspose - Computes matrix Hermitian-transpose times a vector $y = A^H * 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 `MatMultHermitianTranspose`(A,y,y).
2690 
2691   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2692 
2693   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2694 
2695 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2696 @*/
2697 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2698 {
2699   PetscFunctionBegin;
2700   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2701   PetscValidType(mat, 1);
2702   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2703   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2704 
2705   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2706   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2707   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2708   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);
2709   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);
2710   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);
2711   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);
2712   MatCheckPreallocated(mat, 1);
2713 
2714   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2715 #if defined(PETSC_USE_COMPLEX)
2716   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2717     PetscCall(VecLockReadPush(x));
2718     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2719     else PetscUseTypeMethod(mat, mult, x, y);
2720     PetscCall(VecLockReadPop(x));
2721   } else {
2722     Vec w;
2723     PetscCall(VecDuplicate(x, &w));
2724     PetscCall(VecCopy(x, w));
2725     PetscCall(VecConjugate(w));
2726     PetscCall(MatMultTranspose(mat, w, y));
2727     PetscCall(VecDestroy(&w));
2728     PetscCall(VecConjugate(y));
2729   }
2730   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2731 #else
2732   PetscCall(MatMultTranspose(mat, x, y));
2733 #endif
2734   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2735   PetscFunctionReturn(PETSC_SUCCESS);
2736 }
2737 
2738 /*@
2739   MatMultAdd -  Computes $v3 = v2 + A * v1$.
2740 
2741   Neighbor-wise Collective
2742 
2743   Input Parameters:
2744 + mat - the matrix
2745 . v1  - the vector to be multiplied by `mat`
2746 - v2  - the vector to be added to the result
2747 
2748   Output Parameter:
2749 . v3 - the result
2750 
2751   Level: beginner
2752 
2753   Note:
2754   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2755   call `MatMultAdd`(A,v1,v2,v1).
2756 
2757 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2758 @*/
2759 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2760 {
2761   PetscFunctionBegin;
2762   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2763   PetscValidType(mat, 1);
2764   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2765   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2766   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2767 
2768   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2769   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2770   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);
2771   /* 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);
2772      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); */
2773   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);
2774   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);
2775   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2776   MatCheckPreallocated(mat, 1);
2777 
2778   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2779   PetscCall(VecLockReadPush(v1));
2780   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2781   PetscCall(VecLockReadPop(v1));
2782   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2783   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2784   PetscFunctionReturn(PETSC_SUCCESS);
2785 }
2786 
2787 /*@
2788   MatMultTransposeAdd - Computes $v3 = v2 + A^T * v1$.
2789 
2790   Neighbor-wise Collective
2791 
2792   Input Parameters:
2793 + mat - the matrix
2794 . v1  - the vector to be multiplied by the transpose of the matrix
2795 - v2  - the vector to be added to the result
2796 
2797   Output Parameter:
2798 . v3 - the result
2799 
2800   Level: beginner
2801 
2802   Note:
2803   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2804   call `MatMultTransposeAdd`(A,v1,v2,v1).
2805 
2806 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2807 @*/
2808 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2809 {
2810   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2811 
2812   PetscFunctionBegin;
2813   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2814   PetscValidType(mat, 1);
2815   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2816   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2817   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2818 
2819   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2820   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2821   PetscCheck(mat->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);
2822   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);
2823   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);
2824   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2825   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2826   MatCheckPreallocated(mat, 1);
2827 
2828   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2829   PetscCall(VecLockReadPush(v1));
2830   PetscCall((*op)(mat, v1, v2, v3));
2831   PetscCall(VecLockReadPop(v1));
2832   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2833   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2834   PetscFunctionReturn(PETSC_SUCCESS);
2835 }
2836 
2837 /*@
2838   MatMultHermitianTransposeAdd - Computes $v3 = v2 + A^H * v1$.
2839 
2840   Neighbor-wise Collective
2841 
2842   Input Parameters:
2843 + mat - the matrix
2844 . v1  - the vector to be multiplied by the Hermitian transpose
2845 - v2  - the vector to be added to the result
2846 
2847   Output Parameter:
2848 . v3 - the result
2849 
2850   Level: beginner
2851 
2852   Note:
2853   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2854   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2855 
2856 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2857 @*/
2858 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2859 {
2860   PetscFunctionBegin;
2861   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2862   PetscValidType(mat, 1);
2863   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2864   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2865   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2866 
2867   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2868   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2869   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2870   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);
2871   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);
2872   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);
2873   MatCheckPreallocated(mat, 1);
2874 
2875   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2876   PetscCall(VecLockReadPush(v1));
2877   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2878   else {
2879     Vec w, z;
2880     PetscCall(VecDuplicate(v1, &w));
2881     PetscCall(VecCopy(v1, w));
2882     PetscCall(VecConjugate(w));
2883     PetscCall(VecDuplicate(v3, &z));
2884     PetscCall(MatMultTranspose(mat, w, z));
2885     PetscCall(VecDestroy(&w));
2886     PetscCall(VecConjugate(z));
2887     if (v2 != v3) {
2888       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2889     } else {
2890       PetscCall(VecAXPY(v3, 1.0, z));
2891     }
2892     PetscCall(VecDestroy(&z));
2893   }
2894   PetscCall(VecLockReadPop(v1));
2895   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2896   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2897   PetscFunctionReturn(PETSC_SUCCESS);
2898 }
2899 
2900 /*@C
2901   MatGetFactorType - gets the type of factorization a matrix is
2902 
2903   Not Collective
2904 
2905   Input Parameter:
2906 . mat - the matrix
2907 
2908   Output Parameter:
2909 . 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`
2910 
2911   Level: intermediate
2912 
2913 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2914           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2915 @*/
2916 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2917 {
2918   PetscFunctionBegin;
2919   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2920   PetscValidType(mat, 1);
2921   PetscAssertPointer(t, 2);
2922   *t = mat->factortype;
2923   PetscFunctionReturn(PETSC_SUCCESS);
2924 }
2925 
2926 /*@C
2927   MatSetFactorType - sets the type of factorization a matrix is
2928 
2929   Logically Collective
2930 
2931   Input Parameters:
2932 + mat - the matrix
2933 - 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`
2934 
2935   Level: intermediate
2936 
2937 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2938           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2939 @*/
2940 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2941 {
2942   PetscFunctionBegin;
2943   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2944   PetscValidType(mat, 1);
2945   mat->factortype = t;
2946   PetscFunctionReturn(PETSC_SUCCESS);
2947 }
2948 
2949 /*@C
2950   MatGetInfo - Returns information about matrix storage (number of
2951   nonzeros, memory, etc.).
2952 
2953   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2954 
2955   Input Parameters:
2956 + mat  - the matrix
2957 - 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)
2958 
2959   Output Parameter:
2960 . info - matrix information context
2961 
2962   Options Database Key:
2963 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2964 
2965   Notes:
2966   The `MatInfo` context contains a variety of matrix data, including
2967   number of nonzeros allocated and used, number of mallocs during
2968   matrix assembly, etc.  Additional information for factored matrices
2969   is provided (such as the fill ratio, number of mallocs during
2970   factorization, etc.).
2971 
2972   Example:
2973   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2974   data within the MatInfo context.  For example,
2975 .vb
2976       MatInfo info;
2977       Mat     A;
2978       double  mal, nz_a, nz_u;
2979 
2980       MatGetInfo(A, MAT_LOCAL, &info);
2981       mal  = info.mallocs;
2982       nz_a = info.nz_allocated;
2983 .ve
2984 
2985   Fortran users should declare info as a double precision
2986   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2987   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2988   a complete list of parameter names.
2989 .vb
2990       double  precision info(MAT_INFO_SIZE)
2991       double  precision mal, nz_a
2992       Mat     A
2993       integer ierr
2994 
2995       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2996       mal = info(MAT_INFO_MALLOCS)
2997       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2998 .ve
2999 
3000   Level: intermediate
3001 
3002   Developer Note:
3003   The Fortran interface is not autogenerated as the
3004   interface definition cannot be generated correctly [due to `MatInfo` argument]
3005 
3006 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3007 @*/
3008 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3009 {
3010   PetscFunctionBegin;
3011   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3012   PetscValidType(mat, 1);
3013   PetscAssertPointer(info, 3);
3014   MatCheckPreallocated(mat, 1);
3015   PetscUseTypeMethod(mat, getinfo, flag, info);
3016   PetscFunctionReturn(PETSC_SUCCESS);
3017 }
3018 
3019 /*
3020    This is used by external packages where it is not easy to get the info from the actual
3021    matrix factorization.
3022 */
3023 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3024 {
3025   PetscFunctionBegin;
3026   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3027   PetscFunctionReturn(PETSC_SUCCESS);
3028 }
3029 
3030 /*@C
3031   MatLUFactor - Performs in-place LU factorization of matrix.
3032 
3033   Collective
3034 
3035   Input Parameters:
3036 + mat  - the matrix
3037 . row  - row permutation
3038 . col  - column permutation
3039 - info - options for factorization, includes
3040 .vb
3041           fill - expected fill as ratio of original fill.
3042           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3043                    Run with the option -info to determine an optimal value to use
3044 .ve
3045 
3046   Level: developer
3047 
3048   Notes:
3049   Most users should employ the `KSP` interface for linear solvers
3050   instead of working directly with matrix algebra routines such as this.
3051   See, e.g., `KSPCreate()`.
3052 
3053   This changes the state of the matrix to a factored matrix; it cannot be used
3054   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3055 
3056   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3057   when not using `KSP`.
3058 
3059   Developer Note:
3060   The Fortran interface is not autogenerated as the
3061   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3062 
3063 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3064           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3065 @*/
3066 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3067 {
3068   MatFactorInfo tinfo;
3069 
3070   PetscFunctionBegin;
3071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3072   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3073   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3074   if (info) PetscAssertPointer(info, 4);
3075   PetscValidType(mat, 1);
3076   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3077   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3078   MatCheckPreallocated(mat, 1);
3079   if (!info) {
3080     PetscCall(MatFactorInfoInitialize(&tinfo));
3081     info = &tinfo;
3082   }
3083 
3084   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3085   PetscUseTypeMethod(mat, lufactor, row, col, info);
3086   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3087   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3088   PetscFunctionReturn(PETSC_SUCCESS);
3089 }
3090 
3091 /*@C
3092   MatILUFactor - Performs in-place ILU factorization of matrix.
3093 
3094   Collective
3095 
3096   Input Parameters:
3097 + mat  - the matrix
3098 . row  - row permutation
3099 . col  - column permutation
3100 - info - structure containing
3101 .vb
3102       levels - number of levels of fill.
3103       expected fill - as ratio of original fill.
3104       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3105                 missing diagonal entries)
3106 .ve
3107 
3108   Level: developer
3109 
3110   Notes:
3111   Most users should employ the `KSP` interface for linear solvers
3112   instead of working directly with matrix algebra routines such as this.
3113   See, e.g., `KSPCreate()`.
3114 
3115   Probably really in-place only when level of fill is zero, otherwise allocates
3116   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3117   when not using `KSP`.
3118 
3119   Developer Note:
3120   The Fortran interface is not autogenerated as the
3121   interface definition cannot be generated correctly [due to MatFactorInfo]
3122 
3123 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3124 @*/
3125 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3126 {
3127   PetscFunctionBegin;
3128   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3129   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3130   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3131   PetscAssertPointer(info, 4);
3132   PetscValidType(mat, 1);
3133   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3134   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3135   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3136   MatCheckPreallocated(mat, 1);
3137 
3138   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3139   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3140   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3141   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3142   PetscFunctionReturn(PETSC_SUCCESS);
3143 }
3144 
3145 /*@C
3146   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3147   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3148 
3149   Collective
3150 
3151   Input Parameters:
3152 + fact - the factor matrix obtained with `MatGetFactor()`
3153 . mat  - the matrix
3154 . row  - the row permutation
3155 . col  - the column permutation
3156 - info - options for factorization, includes
3157 .vb
3158           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3159           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3160 .ve
3161 
3162   Level: developer
3163 
3164   Notes:
3165   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3166 
3167   Most users should employ the simplified `KSP` interface for linear solvers
3168   instead of working directly with matrix algebra routines such as this.
3169   See, e.g., `KSPCreate()`.
3170 
3171   Developer Note:
3172   The Fortran interface is not autogenerated as the
3173   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3174 
3175 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3176 @*/
3177 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3178 {
3179   MatFactorInfo tinfo;
3180 
3181   PetscFunctionBegin;
3182   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3183   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3184   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3185   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3186   if (info) PetscAssertPointer(info, 5);
3187   PetscValidType(fact, 1);
3188   PetscValidType(mat, 2);
3189   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3190   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3191   MatCheckPreallocated(mat, 2);
3192   if (!info) {
3193     PetscCall(MatFactorInfoInitialize(&tinfo));
3194     info = &tinfo;
3195   }
3196 
3197   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3198   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3199   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3200   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3201   PetscFunctionReturn(PETSC_SUCCESS);
3202 }
3203 
3204 /*@C
3205   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3206   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3207 
3208   Collective
3209 
3210   Input Parameters:
3211 + fact - the factor matrix obtained with `MatGetFactor()`
3212 . mat  - the matrix
3213 - info - options for factorization
3214 
3215   Level: developer
3216 
3217   Notes:
3218   See `MatLUFactor()` for in-place factorization.  See
3219   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3220 
3221   Most users should employ the `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()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3230 @*/
3231 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3232 {
3233   MatFactorInfo tinfo;
3234 
3235   PetscFunctionBegin;
3236   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3238   PetscValidType(fact, 1);
3239   PetscValidType(mat, 2);
3240   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3241   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,
3242              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3243 
3244   MatCheckPreallocated(mat, 2);
3245   if (!info) {
3246     PetscCall(MatFactorInfoInitialize(&tinfo));
3247     info = &tinfo;
3248   }
3249 
3250   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3251   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3252   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3253   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3254   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3255   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3256   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3257   PetscFunctionReturn(PETSC_SUCCESS);
3258 }
3259 
3260 /*@C
3261   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3262   symmetric matrix.
3263 
3264   Collective
3265 
3266   Input Parameters:
3267 + mat  - the matrix
3268 . perm - row and column permutations
3269 - info - expected fill as ratio of original fill
3270 
3271   Level: developer
3272 
3273   Notes:
3274   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3275   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3276 
3277   Most users should employ the `KSP` interface for linear solvers
3278   instead of working directly with matrix algebra routines such as this.
3279   See, e.g., `KSPCreate()`.
3280 
3281   Developer Note:
3282   The Fortran interface is not autogenerated as the
3283   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3284 
3285 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3286           `MatGetOrdering()`
3287 @*/
3288 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3289 {
3290   MatFactorInfo tinfo;
3291 
3292   PetscFunctionBegin;
3293   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3294   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3295   if (info) PetscAssertPointer(info, 3);
3296   PetscValidType(mat, 1);
3297   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3298   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3299   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3300   MatCheckPreallocated(mat, 1);
3301   if (!info) {
3302     PetscCall(MatFactorInfoInitialize(&tinfo));
3303     info = &tinfo;
3304   }
3305 
3306   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3307   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3308   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3309   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3310   PetscFunctionReturn(PETSC_SUCCESS);
3311 }
3312 
3313 /*@C
3314   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3315   of a symmetric matrix.
3316 
3317   Collective
3318 
3319   Input Parameters:
3320 + fact - the factor matrix obtained with `MatGetFactor()`
3321 . mat  - the matrix
3322 . perm - row and column permutations
3323 - info - options for factorization, includes
3324 .vb
3325           fill - expected fill as ratio of original fill.
3326           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3327                    Run with the option -info to determine an optimal value to use
3328 .ve
3329 
3330   Level: developer
3331 
3332   Notes:
3333   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3334   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3335 
3336   Most users should employ the `KSP` interface for linear solvers
3337   instead of working directly with matrix algebra routines such as this.
3338   See, e.g., `KSPCreate()`.
3339 
3340   Developer Note:
3341   The Fortran interface is not autogenerated as the
3342   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3343 
3344 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3345           `MatGetOrdering()`
3346 @*/
3347 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3348 {
3349   MatFactorInfo tinfo;
3350 
3351   PetscFunctionBegin;
3352   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3353   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3354   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3355   if (info) PetscAssertPointer(info, 4);
3356   PetscValidType(fact, 1);
3357   PetscValidType(mat, 2);
3358   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3359   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3360   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3361   MatCheckPreallocated(mat, 2);
3362   if (!info) {
3363     PetscCall(MatFactorInfoInitialize(&tinfo));
3364     info = &tinfo;
3365   }
3366 
3367   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3368   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3369   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3370   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3371   PetscFunctionReturn(PETSC_SUCCESS);
3372 }
3373 
3374 /*@C
3375   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3376   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3377   `MatCholeskyFactorSymbolic()`.
3378 
3379   Collective
3380 
3381   Input Parameters:
3382 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3383 . mat  - the initial matrix that is to be factored
3384 - info - options for factorization
3385 
3386   Level: developer
3387 
3388   Note:
3389   Most users should employ the `KSP` interface for linear solvers
3390   instead of working directly with matrix algebra routines such as this.
3391   See, e.g., `KSPCreate()`.
3392 
3393   Developer Note:
3394   The Fortran interface is not autogenerated as the
3395   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3396 
3397 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3398 @*/
3399 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3400 {
3401   MatFactorInfo tinfo;
3402 
3403   PetscFunctionBegin;
3404   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3405   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3406   PetscValidType(fact, 1);
3407   PetscValidType(mat, 2);
3408   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3409   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,
3410              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3411   MatCheckPreallocated(mat, 2);
3412   if (!info) {
3413     PetscCall(MatFactorInfoInitialize(&tinfo));
3414     info = &tinfo;
3415   }
3416 
3417   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3418   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3419   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3420   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3421   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3422   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3423   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3424   PetscFunctionReturn(PETSC_SUCCESS);
3425 }
3426 
3427 /*@
3428   MatQRFactor - Performs in-place QR factorization of matrix.
3429 
3430   Collective
3431 
3432   Input Parameters:
3433 + mat  - the matrix
3434 . col  - column permutation
3435 - info - options for factorization, includes
3436 .vb
3437           fill - expected fill as ratio of original fill.
3438           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3439                    Run with the option -info to determine an optimal value to use
3440 .ve
3441 
3442   Level: developer
3443 
3444   Notes:
3445   Most users should employ the `KSP` interface for linear solvers
3446   instead of working directly with matrix algebra routines such as this.
3447   See, e.g., `KSPCreate()`.
3448 
3449   This changes the state of the matrix to a factored matrix; it cannot be used
3450   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3451 
3452   Developer Note:
3453   The Fortran interface is not autogenerated as the
3454   interface definition cannot be generated correctly [due to MatFactorInfo]
3455 
3456 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3457           `MatSetUnfactored()`
3458 @*/
3459 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3460 {
3461   PetscFunctionBegin;
3462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3463   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3464   if (info) PetscAssertPointer(info, 3);
3465   PetscValidType(mat, 1);
3466   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3467   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3468   MatCheckPreallocated(mat, 1);
3469   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3470   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3471   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3472   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3473   PetscFunctionReturn(PETSC_SUCCESS);
3474 }
3475 
3476 /*@
3477   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3478   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3479 
3480   Collective
3481 
3482   Input Parameters:
3483 + fact - the factor matrix obtained with `MatGetFactor()`
3484 . mat  - the matrix
3485 . col  - column permutation
3486 - info - options for factorization, includes
3487 .vb
3488           fill - expected fill as ratio of original fill.
3489           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3490                    Run with the option -info to determine an optimal value to use
3491 .ve
3492 
3493   Level: developer
3494 
3495   Note:
3496   Most users should employ the `KSP` interface for linear solvers
3497   instead of working directly with matrix algebra routines such as this.
3498   See, e.g., `KSPCreate()`.
3499 
3500   Developer Note:
3501   The Fortran interface is not autogenerated as the
3502   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3503 
3504 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3505 @*/
3506 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3507 {
3508   MatFactorInfo tinfo;
3509 
3510   PetscFunctionBegin;
3511   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3512   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3513   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3514   if (info) PetscAssertPointer(info, 4);
3515   PetscValidType(fact, 1);
3516   PetscValidType(mat, 2);
3517   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3518   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3519   MatCheckPreallocated(mat, 2);
3520   if (!info) {
3521     PetscCall(MatFactorInfoInitialize(&tinfo));
3522     info = &tinfo;
3523   }
3524 
3525   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3526   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3527   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3528   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3529   PetscFunctionReturn(PETSC_SUCCESS);
3530 }
3531 
3532 /*@
3533   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3534   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3535 
3536   Collective
3537 
3538   Input Parameters:
3539 + fact - the factor matrix obtained with `MatGetFactor()`
3540 . mat  - the matrix
3541 - info - options for factorization
3542 
3543   Level: developer
3544 
3545   Notes:
3546   See `MatQRFactor()` for in-place factorization.
3547 
3548   Most users should employ the `KSP` interface for linear solvers
3549   instead of working directly with matrix algebra routines such as this.
3550   See, e.g., `KSPCreate()`.
3551 
3552   Developer Note:
3553   The Fortran interface is not autogenerated as the
3554   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3555 
3556 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3557 @*/
3558 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3559 {
3560   MatFactorInfo tinfo;
3561 
3562   PetscFunctionBegin;
3563   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3565   PetscValidType(fact, 1);
3566   PetscValidType(mat, 2);
3567   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3568   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,
3569              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3570 
3571   MatCheckPreallocated(mat, 2);
3572   if (!info) {
3573     PetscCall(MatFactorInfoInitialize(&tinfo));
3574     info = &tinfo;
3575   }
3576 
3577   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3578   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3579   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3580   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3581   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3582   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3583   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3584   PetscFunctionReturn(PETSC_SUCCESS);
3585 }
3586 
3587 /*@
3588   MatSolve - Solves $A x = b$, given a factored matrix.
3589 
3590   Neighbor-wise Collective
3591 
3592   Input Parameters:
3593 + mat - the factored matrix
3594 - b   - the right-hand-side vector
3595 
3596   Output Parameter:
3597 . x - the result vector
3598 
3599   Level: developer
3600 
3601   Notes:
3602   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3603   call `MatSolve`(A,x,x).
3604 
3605   Most users should employ the `KSP` interface for linear solvers
3606   instead of working directly with matrix algebra routines such as this.
3607   See, e.g., `KSPCreate()`.
3608 
3609 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3610 @*/
3611 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3612 {
3613   PetscFunctionBegin;
3614   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3615   PetscValidType(mat, 1);
3616   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3617   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3618   PetscCheckSameComm(mat, 1, b, 2);
3619   PetscCheckSameComm(mat, 1, x, 3);
3620   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3621   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);
3622   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);
3623   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);
3624   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3625   MatCheckPreallocated(mat, 1);
3626 
3627   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3628   if (mat->factorerrortype) {
3629     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3630     PetscCall(VecSetInf(x));
3631   } else PetscUseTypeMethod(mat, solve, b, x);
3632   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3633   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3634   PetscFunctionReturn(PETSC_SUCCESS);
3635 }
3636 
3637 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3638 {
3639   Vec      b, x;
3640   PetscInt N, i;
3641   PetscErrorCode (*f)(Mat, Vec, Vec);
3642   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3643 
3644   PetscFunctionBegin;
3645   if (A->factorerrortype) {
3646     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3647     PetscCall(MatSetInf(X));
3648     PetscFunctionReturn(PETSC_SUCCESS);
3649   }
3650   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3651   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3652   PetscCall(MatBoundToCPU(A, &Abound));
3653   if (!Abound) {
3654     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3655     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3656   }
3657 #if PetscDefined(HAVE_CUDA)
3658   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3659   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3660 #elif PetscDefined(HAVE_HIP)
3661   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3662   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3663 #endif
3664   PetscCall(MatGetSize(B, NULL, &N));
3665   for (i = 0; i < N; i++) {
3666     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3667     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3668     PetscCall((*f)(A, b, x));
3669     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3670     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3671   }
3672   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3673   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3674   PetscFunctionReturn(PETSC_SUCCESS);
3675 }
3676 
3677 /*@
3678   MatMatSolve - Solves $A X = B$, given a factored matrix.
3679 
3680   Neighbor-wise Collective
3681 
3682   Input Parameters:
3683 + A - the factored matrix
3684 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3685 
3686   Output Parameter:
3687 . X - the result matrix (dense matrix)
3688 
3689   Level: developer
3690 
3691   Note:
3692   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3693   otherwise, `B` and `X` cannot be the same.
3694 
3695 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3696 @*/
3697 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3698 {
3699   PetscFunctionBegin;
3700   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3701   PetscValidType(A, 1);
3702   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3703   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3704   PetscCheckSameComm(A, 1, B, 2);
3705   PetscCheckSameComm(A, 1, X, 3);
3706   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);
3707   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);
3708   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");
3709   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3710   MatCheckPreallocated(A, 1);
3711 
3712   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3713   if (!A->ops->matsolve) {
3714     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3715     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3716   } else PetscUseTypeMethod(A, matsolve, B, X);
3717   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3718   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3719   PetscFunctionReturn(PETSC_SUCCESS);
3720 }
3721 
3722 /*@
3723   MatMatSolveTranspose - Solves $A^T X = B $, given a factored matrix.
3724 
3725   Neighbor-wise Collective
3726 
3727   Input Parameters:
3728 + A - the factored matrix
3729 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3730 
3731   Output Parameter:
3732 . X - the result matrix (dense matrix)
3733 
3734   Level: developer
3735 
3736   Note:
3737   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3738   call `MatMatSolveTranspose`(A,X,X).
3739 
3740 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3741 @*/
3742 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3743 {
3744   PetscFunctionBegin;
3745   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3746   PetscValidType(A, 1);
3747   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3748   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3749   PetscCheckSameComm(A, 1, B, 2);
3750   PetscCheckSameComm(A, 1, X, 3);
3751   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3752   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);
3753   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);
3754   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);
3755   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");
3756   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3757   MatCheckPreallocated(A, 1);
3758 
3759   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3760   if (!A->ops->matsolvetranspose) {
3761     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3762     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3763   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3764   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3765   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3766   PetscFunctionReturn(PETSC_SUCCESS);
3767 }
3768 
3769 /*@
3770   MatMatTransposeSolve - Solves $A X = B^T$, given a factored matrix.
3771 
3772   Neighbor-wise Collective
3773 
3774   Input Parameters:
3775 + A  - the factored matrix
3776 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3777 
3778   Output Parameter:
3779 . X - the result matrix (dense matrix)
3780 
3781   Level: developer
3782 
3783   Note:
3784   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
3785   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3786 
3787 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3788 @*/
3789 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3790 {
3791   PetscFunctionBegin;
3792   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3793   PetscValidType(A, 1);
3794   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3795   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3796   PetscCheckSameComm(A, 1, Bt, 2);
3797   PetscCheckSameComm(A, 1, X, 3);
3798 
3799   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3800   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);
3801   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);
3802   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");
3803   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3804   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3805   MatCheckPreallocated(A, 1);
3806 
3807   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3808   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3809   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3810   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3811   PetscFunctionReturn(PETSC_SUCCESS);
3812 }
3813 
3814 /*@
3815   MatForwardSolve - Solves $ L x = b $, given a factored matrix, $A = LU $, or
3816   $U^T*D^(1/2) x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3817 
3818   Neighbor-wise Collective
3819 
3820   Input Parameters:
3821 + mat - the factored matrix
3822 - b   - the right-hand-side vector
3823 
3824   Output Parameter:
3825 . x - the result vector
3826 
3827   Level: developer
3828 
3829   Notes:
3830   `MatSolve()` should be used for most applications, as it performs
3831   a forward solve followed by a backward solve.
3832 
3833   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3834   call `MatForwardSolve`(A,x,x).
3835 
3836   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3837   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3838   `MatForwardSolve()` solves $U^T*D y = b$, and
3839   `MatBackwardSolve()` solves $U x = y$.
3840   Thus they do not provide a symmetric preconditioner.
3841 
3842 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3843 @*/
3844 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3845 {
3846   PetscFunctionBegin;
3847   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3848   PetscValidType(mat, 1);
3849   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3850   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3851   PetscCheckSameComm(mat, 1, b, 2);
3852   PetscCheckSameComm(mat, 1, x, 3);
3853   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3854   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);
3855   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);
3856   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);
3857   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3858   MatCheckPreallocated(mat, 1);
3859 
3860   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3861   PetscUseTypeMethod(mat, forwardsolve, b, x);
3862   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3863   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3864   PetscFunctionReturn(PETSC_SUCCESS);
3865 }
3866 
3867 /*@
3868   MatBackwardSolve - Solves $U x = b$, given a factored matrix, $A = LU$.
3869   $D^(1/2) U x = b$, given a factored symmetric matrix, $A = U^T*D*U$,
3870 
3871   Neighbor-wise Collective
3872 
3873   Input Parameters:
3874 + mat - the factored matrix
3875 - b   - the right-hand-side vector
3876 
3877   Output Parameter:
3878 . x - the result vector
3879 
3880   Level: developer
3881 
3882   Notes:
3883   `MatSolve()` should be used for most applications, as it performs
3884   a forward solve followed by a backward solve.
3885 
3886   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3887   call `MatBackwardSolve`(A,x,x).
3888 
3889   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3890   the diagonal blocks are not implemented as $D = D^(1/2) * D^(1/2)$ yet.
3891   `MatForwardSolve()` solves $U^T*D y = b$, and
3892   `MatBackwardSolve()` solves $U x = y$.
3893   Thus they do not provide a symmetric preconditioner.
3894 
3895 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3896 @*/
3897 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3898 {
3899   PetscFunctionBegin;
3900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3901   PetscValidType(mat, 1);
3902   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3903   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3904   PetscCheckSameComm(mat, 1, b, 2);
3905   PetscCheckSameComm(mat, 1, x, 3);
3906   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3907   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);
3908   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);
3909   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);
3910   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3911   MatCheckPreallocated(mat, 1);
3912 
3913   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3914   PetscUseTypeMethod(mat, backwardsolve, b, x);
3915   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3916   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3917   PetscFunctionReturn(PETSC_SUCCESS);
3918 }
3919 
3920 /*@
3921   MatSolveAdd - Computes $x = y + A^{-1}*b$, given a factored matrix.
3922 
3923   Neighbor-wise Collective
3924 
3925   Input Parameters:
3926 + mat - the factored matrix
3927 . b   - the right-hand-side vector
3928 - y   - the vector to be added to
3929 
3930   Output Parameter:
3931 . x - the result vector
3932 
3933   Level: developer
3934 
3935   Note:
3936   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3937   call `MatSolveAdd`(A,x,y,x).
3938 
3939 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3940 @*/
3941 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3942 {
3943   PetscScalar one = 1.0;
3944   Vec         tmp;
3945 
3946   PetscFunctionBegin;
3947   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3948   PetscValidType(mat, 1);
3949   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3950   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3951   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3952   PetscCheckSameComm(mat, 1, b, 2);
3953   PetscCheckSameComm(mat, 1, y, 3);
3954   PetscCheckSameComm(mat, 1, x, 4);
3955   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3956   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
3957   PetscCheck(mat->rmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, b->map->N);
3958   PetscCheck(mat->rmap->N == 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);
3959   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);
3960   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);
3961   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3962   MatCheckPreallocated(mat, 1);
3963 
3964   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3965   if (mat->factorerrortype) {
3966     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3967     PetscCall(VecSetInf(x));
3968   } else if (mat->ops->solveadd) {
3969     PetscUseTypeMethod(mat, solveadd, b, y, x);
3970   } else {
3971     /* do the solve then the add manually */
3972     if (x != y) {
3973       PetscCall(MatSolve(mat, b, x));
3974       PetscCall(VecAXPY(x, one, y));
3975     } else {
3976       PetscCall(VecDuplicate(x, &tmp));
3977       PetscCall(VecCopy(x, tmp));
3978       PetscCall(MatSolve(mat, b, x));
3979       PetscCall(VecAXPY(x, one, tmp));
3980       PetscCall(VecDestroy(&tmp));
3981     }
3982   }
3983   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3984   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3985   PetscFunctionReturn(PETSC_SUCCESS);
3986 }
3987 
3988 /*@
3989   MatSolveTranspose - Solves $A^T x = b$, given a factored matrix.
3990 
3991   Neighbor-wise Collective
3992 
3993   Input Parameters:
3994 + mat - the factored matrix
3995 - b   - the right-hand-side vector
3996 
3997   Output Parameter:
3998 . x - the result vector
3999 
4000   Level: developer
4001 
4002   Notes:
4003   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4004   call `MatSolveTranspose`(A,x,x).
4005 
4006   Most users should employ the `KSP` interface for linear solvers
4007   instead of working directly with matrix algebra routines such as this.
4008   See, e.g., `KSPCreate()`.
4009 
4010 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4011 @*/
4012 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4013 {
4014   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4015 
4016   PetscFunctionBegin;
4017   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4018   PetscValidType(mat, 1);
4019   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4020   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4021   PetscCheckSameComm(mat, 1, b, 2);
4022   PetscCheckSameComm(mat, 1, x, 3);
4023   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4024   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);
4025   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);
4026   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4027   MatCheckPreallocated(mat, 1);
4028   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4029   if (mat->factorerrortype) {
4030     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4031     PetscCall(VecSetInf(x));
4032   } else {
4033     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4034     PetscCall((*f)(mat, b, x));
4035   }
4036   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4037   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4038   PetscFunctionReturn(PETSC_SUCCESS);
4039 }
4040 
4041 /*@
4042   MatSolveTransposeAdd - Computes $x = y + A^{-T} b$
4043   factored matrix.
4044 
4045   Neighbor-wise Collective
4046 
4047   Input Parameters:
4048 + mat - the factored matrix
4049 . b   - the right-hand-side vector
4050 - y   - the vector to be added to
4051 
4052   Output Parameter:
4053 . x - the result vector
4054 
4055   Level: developer
4056 
4057   Note:
4058   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4059   call `MatSolveTransposeAdd`(A,x,y,x).
4060 
4061 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4062 @*/
4063 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4064 {
4065   PetscScalar one = 1.0;
4066   Vec         tmp;
4067   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4068 
4069   PetscFunctionBegin;
4070   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4071   PetscValidType(mat, 1);
4072   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4073   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4074   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4075   PetscCheckSameComm(mat, 1, b, 2);
4076   PetscCheckSameComm(mat, 1, y, 3);
4077   PetscCheckSameComm(mat, 1, x, 4);
4078   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4079   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
4080   PetscCheck(mat->cmap->N == b->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, b->map->N);
4081   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);
4082   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);
4083   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4084   MatCheckPreallocated(mat, 1);
4085 
4086   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4087   if (mat->factorerrortype) {
4088     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4089     PetscCall(VecSetInf(x));
4090   } else if (f) {
4091     PetscCall((*f)(mat, b, y, x));
4092   } else {
4093     /* do the solve then the add manually */
4094     if (x != y) {
4095       PetscCall(MatSolveTranspose(mat, b, x));
4096       PetscCall(VecAXPY(x, one, y));
4097     } else {
4098       PetscCall(VecDuplicate(x, &tmp));
4099       PetscCall(VecCopy(x, tmp));
4100       PetscCall(MatSolveTranspose(mat, b, x));
4101       PetscCall(VecAXPY(x, one, tmp));
4102       PetscCall(VecDestroy(&tmp));
4103     }
4104   }
4105   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4106   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4107   PetscFunctionReturn(PETSC_SUCCESS);
4108 }
4109 
4110 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
4111 /*@
4112   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4113 
4114   Neighbor-wise Collective
4115 
4116   Input Parameters:
4117 + mat   - the matrix
4118 . b     - the right hand side
4119 . omega - the relaxation factor
4120 . flag  - flag indicating the type of SOR (see below)
4121 . shift - diagonal shift
4122 . its   - the number of iterations
4123 - lits  - the number of local iterations
4124 
4125   Output Parameter:
4126 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4127 
4128   SOR Flags:
4129 +     `SOR_FORWARD_SWEEP` - forward SOR
4130 .     `SOR_BACKWARD_SWEEP` - backward SOR
4131 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4132 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4133 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4134 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4135 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4136 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4137   upper/lower triangular part of matrix to
4138   vector (with omega)
4139 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4140 
4141   Level: developer
4142 
4143   Notes:
4144   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4145   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4146   on each processor.
4147 
4148   Application programmers will not generally use `MatSOR()` directly,
4149   but instead will employ the `KSP`/`PC` interface.
4150 
4151   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4152 
4153   Most users should employ the `KSP` interface for linear solvers
4154   instead of working directly with matrix algebra routines such as this.
4155   See, e.g., `KSPCreate()`.
4156 
4157   Vectors `x` and `b` CANNOT be the same
4158 
4159   The flags are implemented as bitwise inclusive or operations.
4160   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4161   to specify a zero initial guess for SSOR.
4162 
4163   Developer Note:
4164   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4165 
4166 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4167 @*/
4168 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4169 {
4170   PetscFunctionBegin;
4171   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4172   PetscValidType(mat, 1);
4173   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4174   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4175   PetscCheckSameComm(mat, 1, b, 2);
4176   PetscCheckSameComm(mat, 1, x, 8);
4177   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4178   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4179   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);
4180   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);
4181   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);
4182   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4183   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4184   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4185 
4186   MatCheckPreallocated(mat, 1);
4187   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4188   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4189   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4190   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4191   PetscFunctionReturn(PETSC_SUCCESS);
4192 }
4193 
4194 /*
4195       Default matrix copy routine.
4196 */
4197 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4198 {
4199   PetscInt           i, rstart = 0, rend = 0, nz;
4200   const PetscInt    *cwork;
4201   const PetscScalar *vwork;
4202 
4203   PetscFunctionBegin;
4204   if (B->assembled) PetscCall(MatZeroEntries(B));
4205   if (str == SAME_NONZERO_PATTERN) {
4206     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4207     for (i = rstart; i < rend; i++) {
4208       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4209       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4210       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4211     }
4212   } else {
4213     PetscCall(MatAYPX(B, 0.0, A, str));
4214   }
4215   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4216   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4217   PetscFunctionReturn(PETSC_SUCCESS);
4218 }
4219 
4220 /*@
4221   MatCopy - Copies a matrix to another matrix.
4222 
4223   Collective
4224 
4225   Input Parameters:
4226 + A   - the matrix
4227 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4228 
4229   Output Parameter:
4230 . B - where the copy is put
4231 
4232   Level: intermediate
4233 
4234   Notes:
4235   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4236 
4237   `MatCopy()` copies the matrix entries of a matrix to another existing
4238   matrix (after first zeroing the second matrix).  A related routine is
4239   `MatConvert()`, which first creates a new matrix and then copies the data.
4240 
4241 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4242 @*/
4243 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4244 {
4245   PetscInt i;
4246 
4247   PetscFunctionBegin;
4248   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4249   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4250   PetscValidType(A, 1);
4251   PetscValidType(B, 2);
4252   PetscCheckSameComm(A, 1, B, 2);
4253   MatCheckPreallocated(B, 2);
4254   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4255   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4256   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,
4257              A->cmap->N, B->cmap->N);
4258   MatCheckPreallocated(A, 1);
4259   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4260 
4261   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4262   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4263   else PetscCall(MatCopy_Basic(A, B, str));
4264 
4265   B->stencil.dim = A->stencil.dim;
4266   B->stencil.noc = A->stencil.noc;
4267   for (i = 0; i <= A->stencil.dim + (A->stencil.noc ? 0 : -1); i++) {
4268     B->stencil.dims[i]   = A->stencil.dims[i];
4269     B->stencil.starts[i] = A->stencil.starts[i];
4270   }
4271 
4272   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4273   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4274   PetscFunctionReturn(PETSC_SUCCESS);
4275 }
4276 
4277 /*@C
4278   MatConvert - Converts a matrix to another matrix, either of the same
4279   or different type.
4280 
4281   Collective
4282 
4283   Input Parameters:
4284 + mat     - the matrix
4285 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4286    same type as the original matrix.
4287 - reuse   - denotes if the destination matrix is to be created or reused.
4288    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
4289    `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).
4290 
4291   Output Parameter:
4292 . M - pointer to place new matrix
4293 
4294   Level: intermediate
4295 
4296   Notes:
4297   `MatConvert()` first creates a new matrix and then copies the data from
4298   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4299   entries of one matrix to another already existing matrix context.
4300 
4301   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4302   the MPI communicator of the generated matrix is always the same as the communicator
4303   of the input matrix.
4304 
4305 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4306 @*/
4307 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4308 {
4309   PetscBool  sametype, issame, flg;
4310   PetscBool3 issymmetric, ishermitian;
4311   char       convname[256], mtype[256];
4312   Mat        B;
4313 
4314   PetscFunctionBegin;
4315   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4316   PetscValidType(mat, 1);
4317   PetscAssertPointer(M, 4);
4318   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4319   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4320   MatCheckPreallocated(mat, 1);
4321 
4322   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4323   if (flg) newtype = mtype;
4324 
4325   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4326   PetscCall(PetscStrcmp(newtype, "same", &issame));
4327   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4328   if (reuse == MAT_REUSE_MATRIX) {
4329     PetscValidHeaderSpecific(*M, MAT_CLASSID, 4);
4330     PetscCheck(mat != *M, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4331   }
4332 
4333   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4334     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4335     PetscFunctionReturn(PETSC_SUCCESS);
4336   }
4337 
4338   /* Cache Mat options because some converters use MatHeaderReplace  */
4339   issymmetric = mat->symmetric;
4340   ishermitian = mat->hermitian;
4341 
4342   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4343     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4344     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4345   } else {
4346     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4347     const char *prefix[3]                                 = {"seq", "mpi", ""};
4348     PetscInt    i;
4349     /*
4350        Order of precedence:
4351        0) See if newtype is a superclass of the current matrix.
4352        1) See if a specialized converter is known to the current matrix.
4353        2) See if a specialized converter is known to the desired matrix class.
4354        3) See if a good general converter is registered for the desired class
4355           (as of 6/27/03 only MATMPIADJ falls into this category).
4356        4) See if a good general converter is known for the current matrix.
4357        5) Use a really basic converter.
4358     */
4359 
4360     /* 0) See if newtype is a superclass of the current matrix.
4361           i.e mat is mpiaij and newtype is aij */
4362     for (i = 0; i < 2; i++) {
4363       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4365       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4366       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4367       if (flg) {
4368         if (reuse == MAT_INPLACE_MATRIX) {
4369           PetscCall(PetscInfo(mat, "Early return\n"));
4370           PetscFunctionReturn(PETSC_SUCCESS);
4371         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4372           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4373           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4374           PetscFunctionReturn(PETSC_SUCCESS);
4375         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4376           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4377           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4378           PetscFunctionReturn(PETSC_SUCCESS);
4379         }
4380       }
4381     }
4382     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4383     for (i = 0; i < 3; i++) {
4384       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4385       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4386       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4387       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4388       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4389       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4390       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4391       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4392       if (conv) goto foundconv;
4393     }
4394 
4395     /* 2)  See if a specialized converter is known to the desired matrix class. */
4396     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4397     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4398     PetscCall(MatSetType(B, newtype));
4399     for (i = 0; i < 3; i++) {
4400       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4401       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4402       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4403       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4404       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4405       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4406       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4407       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4408       if (conv) {
4409         PetscCall(MatDestroy(&B));
4410         goto foundconv;
4411       }
4412     }
4413 
4414     /* 3) See if a good general converter is registered for the desired class */
4415     conv = B->ops->convertfrom;
4416     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4417     PetscCall(MatDestroy(&B));
4418     if (conv) goto foundconv;
4419 
4420     /* 4) See if a good general converter is known for the current matrix */
4421     if (mat->ops->convert) conv = mat->ops->convert;
4422     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4423     if (conv) goto foundconv;
4424 
4425     /* 5) Use a really basic converter. */
4426     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4427     conv = MatConvert_Basic;
4428 
4429   foundconv:
4430     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4431     PetscCall((*conv)(mat, newtype, reuse, M));
4432     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4433       /* the block sizes must be same if the mappings are copied over */
4434       (*M)->rmap->bs = mat->rmap->bs;
4435       (*M)->cmap->bs = mat->cmap->bs;
4436       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4437       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4438       (*M)->rmap->mapping = mat->rmap->mapping;
4439       (*M)->cmap->mapping = mat->cmap->mapping;
4440     }
4441     (*M)->stencil.dim = mat->stencil.dim;
4442     (*M)->stencil.noc = mat->stencil.noc;
4443     for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4444       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4445       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4446     }
4447     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4448   }
4449   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4450 
4451   /* Copy Mat options */
4452   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4453   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4454   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4455   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4456   PetscFunctionReturn(PETSC_SUCCESS);
4457 }
4458 
4459 /*@C
4460   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4461 
4462   Not Collective
4463 
4464   Input Parameter:
4465 . mat - the matrix, must be a factored matrix
4466 
4467   Output Parameter:
4468 . type - the string name of the package (do not free this string)
4469 
4470   Level: intermediate
4471 
4472   Fortran Note:
4473   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4474 
4475 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4476 @*/
4477 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4478 {
4479   PetscErrorCode (*conv)(Mat, MatSolverType *);
4480 
4481   PetscFunctionBegin;
4482   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4483   PetscValidType(mat, 1);
4484   PetscAssertPointer(type, 2);
4485   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4486   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4487   if (conv) PetscCall((*conv)(mat, type));
4488   else *type = MATSOLVERPETSC;
4489   PetscFunctionReturn(PETSC_SUCCESS);
4490 }
4491 
4492 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4493 struct _MatSolverTypeForSpecifcType {
4494   MatType mtype;
4495   /* no entry for MAT_FACTOR_NONE */
4496   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4497   MatSolverTypeForSpecifcType next;
4498 };
4499 
4500 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4501 struct _MatSolverTypeHolder {
4502   char                       *name;
4503   MatSolverTypeForSpecifcType handlers;
4504   MatSolverTypeHolder         next;
4505 };
4506 
4507 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4508 
4509 /*@C
4510   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4511 
4512   Input Parameters:
4513 + package      - name of the package, for example petsc or superlu
4514 . mtype        - the matrix type that works with this package
4515 . ftype        - the type of factorization supported by the package
4516 - createfactor - routine that will create the factored matrix ready to be used
4517 
4518   Level: developer
4519 
4520 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`,
4521   `MatGetFactor()`
4522 @*/
4523 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4524 {
4525   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4526   PetscBool                   flg;
4527   MatSolverTypeForSpecifcType inext, iprev = NULL;
4528 
4529   PetscFunctionBegin;
4530   PetscCall(MatInitializePackage());
4531   if (!next) {
4532     PetscCall(PetscNew(&MatSolverTypeHolders));
4533     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4534     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4535     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4536     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4537     PetscFunctionReturn(PETSC_SUCCESS);
4538   }
4539   while (next) {
4540     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4541     if (flg) {
4542       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4543       inext = next->handlers;
4544       while (inext) {
4545         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4546         if (flg) {
4547           inext->createfactor[(int)ftype - 1] = createfactor;
4548           PetscFunctionReturn(PETSC_SUCCESS);
4549         }
4550         iprev = inext;
4551         inext = inext->next;
4552       }
4553       PetscCall(PetscNew(&iprev->next));
4554       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4555       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4556       PetscFunctionReturn(PETSC_SUCCESS);
4557     }
4558     prev = next;
4559     next = next->next;
4560   }
4561   PetscCall(PetscNew(&prev->next));
4562   PetscCall(PetscStrallocpy(package, &prev->next->name));
4563   PetscCall(PetscNew(&prev->next->handlers));
4564   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4565   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4566   PetscFunctionReturn(PETSC_SUCCESS);
4567 }
4568 
4569 /*@C
4570   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4571 
4572   Input Parameters:
4573 + 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
4574 . ftype - the type of factorization supported by the type
4575 - mtype - the matrix type that works with this type
4576 
4577   Output Parameters:
4578 + foundtype    - `PETSC_TRUE` if the type was registered
4579 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4580 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4581 
4582   Calling sequence of `createfactor`:
4583 + A     - the matrix providing the factor matrix
4584 . mtype - the `MatType` of the factor requested
4585 - B     - the new factor matrix that responds to MatXXFactorSymbolic,Numeric() functions, such as `MatLUFactorSymbolic()`
4586 
4587   Level: developer
4588 
4589   Note:
4590   When `type` is `NULL` the available functions are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4591   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4592   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4593 
4594 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`,
4595           `MatInitializePackage()`
4596 @*/
4597 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat A, MatFactorType mtype, Mat *B))
4598 {
4599   MatSolverTypeHolder         next = MatSolverTypeHolders;
4600   PetscBool                   flg;
4601   MatSolverTypeForSpecifcType inext;
4602 
4603   PetscFunctionBegin;
4604   if (foundtype) *foundtype = PETSC_FALSE;
4605   if (foundmtype) *foundmtype = PETSC_FALSE;
4606   if (createfactor) *createfactor = NULL;
4607 
4608   if (type) {
4609     while (next) {
4610       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4611       if (flg) {
4612         if (foundtype) *foundtype = PETSC_TRUE;
4613         inext = next->handlers;
4614         while (inext) {
4615           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4616           if (flg) {
4617             if (foundmtype) *foundmtype = PETSC_TRUE;
4618             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4619             PetscFunctionReturn(PETSC_SUCCESS);
4620           }
4621           inext = inext->next;
4622         }
4623       }
4624       next = next->next;
4625     }
4626   } else {
4627     while (next) {
4628       inext = next->handlers;
4629       while (inext) {
4630         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4631         if (flg && inext->createfactor[(int)ftype - 1]) {
4632           if (foundtype) *foundtype = PETSC_TRUE;
4633           if (foundmtype) *foundmtype = PETSC_TRUE;
4634           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4635           PetscFunctionReturn(PETSC_SUCCESS);
4636         }
4637         inext = inext->next;
4638       }
4639       next = next->next;
4640     }
4641     /* try with base classes inext->mtype */
4642     next = MatSolverTypeHolders;
4643     while (next) {
4644       inext = next->handlers;
4645       while (inext) {
4646         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4647         if (flg && inext->createfactor[(int)ftype - 1]) {
4648           if (foundtype) *foundtype = PETSC_TRUE;
4649           if (foundmtype) *foundmtype = PETSC_TRUE;
4650           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4651           PetscFunctionReturn(PETSC_SUCCESS);
4652         }
4653         inext = inext->next;
4654       }
4655       next = next->next;
4656     }
4657   }
4658   PetscFunctionReturn(PETSC_SUCCESS);
4659 }
4660 
4661 PetscErrorCode MatSolverTypeDestroy(void)
4662 {
4663   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4664   MatSolverTypeForSpecifcType inext, iprev;
4665 
4666   PetscFunctionBegin;
4667   while (next) {
4668     PetscCall(PetscFree(next->name));
4669     inext = next->handlers;
4670     while (inext) {
4671       PetscCall(PetscFree(inext->mtype));
4672       iprev = inext;
4673       inext = inext->next;
4674       PetscCall(PetscFree(iprev));
4675     }
4676     prev = next;
4677     next = next->next;
4678     PetscCall(PetscFree(prev));
4679   }
4680   MatSolverTypeHolders = NULL;
4681   PetscFunctionReturn(PETSC_SUCCESS);
4682 }
4683 
4684 /*@C
4685   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4686 
4687   Logically Collective
4688 
4689   Input Parameter:
4690 . mat - the matrix
4691 
4692   Output Parameter:
4693 . flg - `PETSC_TRUE` if uses the ordering
4694 
4695   Level: developer
4696 
4697   Note:
4698   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4699   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4700 
4701 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4702 @*/
4703 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4704 {
4705   PetscFunctionBegin;
4706   *flg = mat->canuseordering;
4707   PetscFunctionReturn(PETSC_SUCCESS);
4708 }
4709 
4710 /*@C
4711   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4712 
4713   Logically Collective
4714 
4715   Input Parameters:
4716 + mat   - the matrix obtained with `MatGetFactor()`
4717 - ftype - the factorization type to be used
4718 
4719   Output Parameter:
4720 . otype - the preferred ordering type
4721 
4722   Level: developer
4723 
4724 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4725 @*/
4726 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4727 {
4728   PetscFunctionBegin;
4729   *otype = mat->preferredordering[ftype];
4730   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4731   PetscFunctionReturn(PETSC_SUCCESS);
4732 }
4733 
4734 /*@C
4735   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic,Numeric()
4736 
4737   Collective
4738 
4739   Input Parameters:
4740 + mat   - the matrix
4741 . 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
4742           the other criteria is returned
4743 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4744 
4745   Output Parameter:
4746 . f - the factor matrix used with MatXXFactorSymbolic,Numeric() calls. Can be `NULL` in some cases, see notes below.
4747 
4748   Options Database Keys:
4749 + -pc_factor_mat_solver_type <type>             - choose the type at run time. When using `KSP` solvers
4750 - -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4751                                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4752 
4753   Level: intermediate
4754 
4755   Notes:
4756   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4757   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4758 
4759   Users usually access the factorization solvers via `KSP`
4760 
4761   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4762   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
4763 
4764   When `type` is `NULL` the available results are searched for based on the order of the calls to `MatSolverTypeRegister()` in `MatInitializePackage()`.
4765   Since different PETSc configurations may have different external solvers, seemingly identical runs with different PETSc configurations may use a different solver.
4766   For example if one configuration had --download-mumps while a different one had --download-superlu_dist.
4767 
4768   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4769   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4770   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4771 
4772   Developer Note:
4773   This should actually be called `MatCreateFactor()` since it creates a new factor object
4774 
4775 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`,
4776           `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`, `MatSolverTypeGet()`
4777           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatInitializePackage()`
4778 @*/
4779 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4780 {
4781   PetscBool foundtype, foundmtype;
4782   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4783 
4784   PetscFunctionBegin;
4785   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4786   PetscValidType(mat, 1);
4787 
4788   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4789   MatCheckPreallocated(mat, 1);
4790 
4791   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4792   if (!foundtype) {
4793     if (type) {
4794       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],
4795               ((PetscObject)mat)->type_name, type);
4796     } else {
4797       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);
4798     }
4799   }
4800   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4801   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);
4802 
4803   PetscCall((*conv)(mat, ftype, f));
4804   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4805   PetscFunctionReturn(PETSC_SUCCESS);
4806 }
4807 
4808 /*@C
4809   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4810 
4811   Not Collective
4812 
4813   Input Parameters:
4814 + mat   - the matrix
4815 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4816 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4817 
4818   Output Parameter:
4819 . flg - PETSC_TRUE if the factorization is available
4820 
4821   Level: intermediate
4822 
4823   Notes:
4824   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4825   such as pastix, superlu, mumps etc.
4826 
4827   PETSc must have been ./configure to use the external solver, using the option --download-package
4828 
4829   Developer Note:
4830   This should actually be called `MatCreateFactorAvailable()` since `MatGetFactor()` creates a new factor object
4831 
4832 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4833           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`, `MatSolverTypeGet()`
4834 @*/
4835 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4836 {
4837   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4838 
4839   PetscFunctionBegin;
4840   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4841   PetscAssertPointer(flg, 4);
4842 
4843   *flg = PETSC_FALSE;
4844   if (!((PetscObject)mat)->type_name) PetscFunctionReturn(PETSC_SUCCESS);
4845 
4846   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4847   MatCheckPreallocated(mat, 1);
4848 
4849   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4850   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4851   PetscFunctionReturn(PETSC_SUCCESS);
4852 }
4853 
4854 /*@
4855   MatDuplicate - Duplicates a matrix including the non-zero structure.
4856 
4857   Collective
4858 
4859   Input Parameters:
4860 + mat - the matrix
4861 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4862         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4863 
4864   Output Parameter:
4865 . M - pointer to place new matrix
4866 
4867   Level: intermediate
4868 
4869   Notes:
4870   You cannot change the nonzero pattern for the parent or child matrix later if you use `MAT_SHARE_NONZERO_PATTERN`.
4871 
4872   If `op` is not `MAT_COPY_VALUES` the numerical values in the new matrix are zeroed.
4873 
4874   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.
4875 
4876   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the matrix data structure of `mat`
4877   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4878   User should not use `MatDuplicate()` to create new matrix `M` if `M` is intended to be reused as the product of matrix operation.
4879 
4880 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4881 @*/
4882 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4883 {
4884   Mat         B;
4885   VecType     vtype;
4886   PetscInt    i;
4887   PetscObject dm, container_h, container_d;
4888   void (*viewf)(void);
4889 
4890   PetscFunctionBegin;
4891   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4892   PetscValidType(mat, 1);
4893   PetscAssertPointer(M, 3);
4894   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4895   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4896   MatCheckPreallocated(mat, 1);
4897 
4898   *M = NULL;
4899   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4900   PetscUseTypeMethod(mat, duplicate, op, M);
4901   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4902   B = *M;
4903 
4904   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4905   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4906   PetscCall(MatGetVecType(mat, &vtype));
4907   PetscCall(MatSetVecType(B, vtype));
4908 
4909   B->stencil.dim = mat->stencil.dim;
4910   B->stencil.noc = mat->stencil.noc;
4911   for (i = 0; i <= mat->stencil.dim + (mat->stencil.noc ? 0 : -1); i++) {
4912     B->stencil.dims[i]   = mat->stencil.dims[i];
4913     B->stencil.starts[i] = mat->stencil.starts[i];
4914   }
4915 
4916   B->nooffproczerorows = mat->nooffproczerorows;
4917   B->nooffprocentries  = mat->nooffprocentries;
4918 
4919   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4920   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4921   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4922   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4923   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4924   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4925   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4926   PetscFunctionReturn(PETSC_SUCCESS);
4927 }
4928 
4929 /*@
4930   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4931 
4932   Logically Collective
4933 
4934   Input Parameter:
4935 . mat - the matrix
4936 
4937   Output Parameter:
4938 . v - the diagonal of the matrix
4939 
4940   Level: intermediate
4941 
4942   Note:
4943   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4944   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4945   is larger than `ndiag`, the values of the remaining entries are unspecified.
4946 
4947   Currently only correct in parallel for square matrices.
4948 
4949 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4950 @*/
4951 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4952 {
4953   PetscFunctionBegin;
4954   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4955   PetscValidType(mat, 1);
4956   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4957   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4958   MatCheckPreallocated(mat, 1);
4959   if (PetscDefined(USE_DEBUG)) {
4960     PetscInt nv, row, col, ndiag;
4961 
4962     PetscCall(VecGetLocalSize(v, &nv));
4963     PetscCall(MatGetLocalSize(mat, &row, &col));
4964     ndiag = PetscMin(row, col);
4965     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);
4966   }
4967 
4968   PetscUseTypeMethod(mat, getdiagonal, v);
4969   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4970   PetscFunctionReturn(PETSC_SUCCESS);
4971 }
4972 
4973 /*@C
4974   MatGetRowMin - Gets the minimum value (of the real part) of each
4975   row of the matrix
4976 
4977   Logically Collective
4978 
4979   Input Parameter:
4980 . mat - the matrix
4981 
4982   Output Parameters:
4983 + v   - the vector for storing the maximums
4984 - idx - the indices of the column found for each row (optional)
4985 
4986   Level: intermediate
4987 
4988   Note:
4989   The result of this call are the same as if one converted the matrix to dense format
4990   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4991 
4992   This code is only implemented for a couple of matrix formats.
4993 
4994 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4995           `MatGetRowMax()`
4996 @*/
4997 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4998 {
4999   PetscFunctionBegin;
5000   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5001   PetscValidType(mat, 1);
5002   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5003   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5004 
5005   if (!mat->cmap->N) {
5006     PetscCall(VecSet(v, PETSC_MAX_REAL));
5007     if (idx) {
5008       PetscInt i, m = mat->rmap->n;
5009       for (i = 0; i < m; i++) idx[i] = -1;
5010     }
5011   } else {
5012     MatCheckPreallocated(mat, 1);
5013   }
5014   PetscUseTypeMethod(mat, getrowmin, v, idx);
5015   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5016   PetscFunctionReturn(PETSC_SUCCESS);
5017 }
5018 
5019 /*@C
5020   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
5021   row of the matrix
5022 
5023   Logically Collective
5024 
5025   Input Parameter:
5026 . mat - the matrix
5027 
5028   Output Parameters:
5029 + v   - the vector for storing the minimums
5030 - idx - the indices of the column found for each row (or `NULL` if not needed)
5031 
5032   Level: intermediate
5033 
5034   Notes:
5035   if a row is completely empty or has only 0.0 values then the `idx` value for that
5036   row is 0 (the first column).
5037 
5038   This code is only implemented for a couple of matrix formats.
5039 
5040 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5041 @*/
5042 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5043 {
5044   PetscFunctionBegin;
5045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5046   PetscValidType(mat, 1);
5047   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5048   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5049   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5050 
5051   if (!mat->cmap->N) {
5052     PetscCall(VecSet(v, 0.0));
5053     if (idx) {
5054       PetscInt i, m = mat->rmap->n;
5055       for (i = 0; i < m; i++) idx[i] = -1;
5056     }
5057   } else {
5058     MatCheckPreallocated(mat, 1);
5059     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5060     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5061   }
5062   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5063   PetscFunctionReturn(PETSC_SUCCESS);
5064 }
5065 
5066 /*@C
5067   MatGetRowMax - Gets the maximum value (of the real part) of each
5068   row of the matrix
5069 
5070   Logically Collective
5071 
5072   Input Parameter:
5073 . mat - the matrix
5074 
5075   Output Parameters:
5076 + v   - the vector for storing the maximums
5077 - idx - the indices of the column found for each row (optional)
5078 
5079   Level: intermediate
5080 
5081   Notes:
5082   The result of this call are the same as if one converted the matrix to dense format
5083   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5084 
5085   This code is only implemented for a couple of matrix formats.
5086 
5087 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5088 @*/
5089 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5090 {
5091   PetscFunctionBegin;
5092   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5093   PetscValidType(mat, 1);
5094   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5095   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5096 
5097   if (!mat->cmap->N) {
5098     PetscCall(VecSet(v, PETSC_MIN_REAL));
5099     if (idx) {
5100       PetscInt i, m = mat->rmap->n;
5101       for (i = 0; i < m; i++) idx[i] = -1;
5102     }
5103   } else {
5104     MatCheckPreallocated(mat, 1);
5105     PetscUseTypeMethod(mat, getrowmax, v, idx);
5106   }
5107   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5108   PetscFunctionReturn(PETSC_SUCCESS);
5109 }
5110 
5111 /*@C
5112   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5113   row of the matrix
5114 
5115   Logically Collective
5116 
5117   Input Parameter:
5118 . mat - the matrix
5119 
5120   Output Parameters:
5121 + v   - the vector for storing the maximums
5122 - idx - the indices of the column found for each row (or `NULL` if not needed)
5123 
5124   Level: intermediate
5125 
5126   Notes:
5127   if a row is completely empty or has only 0.0 values then the `idx` value for that
5128   row is 0 (the first column).
5129 
5130   This code is only implemented for a couple of matrix formats.
5131 
5132 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowSum()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5133 @*/
5134 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5135 {
5136   PetscFunctionBegin;
5137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5138   PetscValidType(mat, 1);
5139   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5140   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5141 
5142   if (!mat->cmap->N) {
5143     PetscCall(VecSet(v, 0.0));
5144     if (idx) {
5145       PetscInt i, m = mat->rmap->n;
5146       for (i = 0; i < m; i++) idx[i] = -1;
5147     }
5148   } else {
5149     MatCheckPreallocated(mat, 1);
5150     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5151     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5152   }
5153   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5154   PetscFunctionReturn(PETSC_SUCCESS);
5155 }
5156 
5157 /*@C
5158   MatGetRowSumAbs - Gets the sum value (in absolute value) of each row of the matrix
5159 
5160   Logically Collective
5161 
5162   Input Parameter:
5163 . mat - the matrix
5164 
5165   Output Parameter:
5166 . v - the vector for storing the sum
5167 
5168   Level: intermediate
5169 
5170   This code is only implemented for a couple of matrix formats.
5171 
5172 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5173 @*/
5174 PetscErrorCode MatGetRowSumAbs(Mat mat, Vec v)
5175 {
5176   PetscFunctionBegin;
5177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5178   PetscValidType(mat, 1);
5179   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5180   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5181 
5182   if (!mat->cmap->N) {
5183     PetscCall(VecSet(v, 0.0));
5184   } else {
5185     MatCheckPreallocated(mat, 1);
5186     PetscUseTypeMethod(mat, getrowsumabs, v);
5187   }
5188   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5189   PetscFunctionReturn(PETSC_SUCCESS);
5190 }
5191 
5192 /*@
5193   MatGetRowSum - Gets the sum of each row of the matrix
5194 
5195   Logically or Neighborhood Collective
5196 
5197   Input Parameter:
5198 . mat - the matrix
5199 
5200   Output Parameter:
5201 . v - the vector for storing the sum of rows
5202 
5203   Level: intermediate
5204 
5205   Note:
5206   This code is slow since it is not currently specialized for different formats
5207 
5208 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`, `MatGetRowSumAbs()`
5209 @*/
5210 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5211 {
5212   Vec ones;
5213 
5214   PetscFunctionBegin;
5215   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5216   PetscValidType(mat, 1);
5217   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5218   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5219   MatCheckPreallocated(mat, 1);
5220   PetscCall(MatCreateVecs(mat, &ones, NULL));
5221   PetscCall(VecSet(ones, 1.));
5222   PetscCall(MatMult(mat, ones, v));
5223   PetscCall(VecDestroy(&ones));
5224   PetscFunctionReturn(PETSC_SUCCESS);
5225 }
5226 
5227 /*@
5228   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5229   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5230 
5231   Collective
5232 
5233   Input Parameter:
5234 . mat - the matrix to provide the transpose
5235 
5236   Output Parameter:
5237 . 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
5238 
5239   Level: advanced
5240 
5241   Note:
5242   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
5243   routine allows bypassing that call.
5244 
5245 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5246 @*/
5247 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5248 {
5249   PetscContainer  rB = NULL;
5250   MatParentState *rb = NULL;
5251 
5252   PetscFunctionBegin;
5253   PetscCall(PetscNew(&rb));
5254   rb->id    = ((PetscObject)mat)->id;
5255   rb->state = 0;
5256   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5257   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5258   PetscCall(PetscContainerSetPointer(rB, rb));
5259   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5260   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5261   PetscCall(PetscObjectDereference((PetscObject)rB));
5262   PetscFunctionReturn(PETSC_SUCCESS);
5263 }
5264 
5265 /*@
5266   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5267 
5268   Collective
5269 
5270   Input Parameters:
5271 + mat   - the matrix to transpose
5272 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5273 
5274   Output Parameter:
5275 . B - the transpose
5276 
5277   Level: intermediate
5278 
5279   Notes:
5280   If you use `MAT_INPLACE_MATRIX` then you must pass in `&mat` for `B`
5281 
5282   `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
5283   transpose, call `MatTransposeSetPrecursor(mat, B)` before calling this routine.
5284 
5285   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.
5286 
5287   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5288 
5289   If mat is unchanged from the last call this function returns immediately without recomputing the result
5290 
5291   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5292 
5293 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5294           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5295 @*/
5296 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5297 {
5298   PetscContainer  rB = NULL;
5299   MatParentState *rb = NULL;
5300 
5301   PetscFunctionBegin;
5302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5303   PetscValidType(mat, 1);
5304   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5305   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5306   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5307   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5308   MatCheckPreallocated(mat, 1);
5309   if (reuse == MAT_REUSE_MATRIX) {
5310     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5311     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5312     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5313     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5314     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5315   }
5316 
5317   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5318   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5319     PetscUseTypeMethod(mat, transpose, reuse, B);
5320     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5321   }
5322   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5323 
5324   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5325   if (reuse != MAT_INPLACE_MATRIX) {
5326     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5327     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5328     rb->state        = ((PetscObject)mat)->state;
5329     rb->nonzerostate = mat->nonzerostate;
5330   }
5331   PetscFunctionReturn(PETSC_SUCCESS);
5332 }
5333 
5334 /*@
5335   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5336 
5337   Collective
5338 
5339   Input Parameter:
5340 . A - the matrix to transpose
5341 
5342   Output Parameter:
5343 . 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
5344       numerical portion.
5345 
5346   Level: intermediate
5347 
5348   Note:
5349   This is not supported for many matrix types, use `MatTranspose()` in those cases
5350 
5351 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5352 @*/
5353 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5354 {
5355   PetscFunctionBegin;
5356   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5357   PetscValidType(A, 1);
5358   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5359   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5360   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5361   PetscUseTypeMethod(A, transposesymbolic, B);
5362   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5363 
5364   PetscCall(MatTransposeSetPrecursor(A, *B));
5365   PetscFunctionReturn(PETSC_SUCCESS);
5366 }
5367 
5368 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5369 {
5370   PetscContainer  rB;
5371   MatParentState *rb;
5372 
5373   PetscFunctionBegin;
5374   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5375   PetscValidType(A, 1);
5376   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5377   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5378   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5379   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5380   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5381   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5382   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5383   PetscFunctionReturn(PETSC_SUCCESS);
5384 }
5385 
5386 /*@
5387   MatIsTranspose - Test whether a matrix is another one's transpose,
5388   or its own, in which case it tests symmetry.
5389 
5390   Collective
5391 
5392   Input Parameters:
5393 + A   - the matrix to test
5394 . B   - the matrix to test against, this can equal the first parameter
5395 - tol - tolerance, differences between entries smaller than this are counted as zero
5396 
5397   Output Parameter:
5398 . flg - the result
5399 
5400   Level: intermediate
5401 
5402   Notes:
5403   Only available for `MATAIJ` matrices.
5404 
5405   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5406   test involves parallel copies of the block off-diagonal parts of the matrix.
5407 
5408 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5409 @*/
5410 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5411 {
5412   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5413 
5414   PetscFunctionBegin;
5415   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5416   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5417   PetscAssertPointer(flg, 4);
5418   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5419   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5420   *flg = PETSC_FALSE;
5421   if (f && g) {
5422     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5423     PetscCall((*f)(A, B, tol, flg));
5424   } else {
5425     MatType mattype;
5426 
5427     PetscCall(MatGetType(f ? B : A, &mattype));
5428     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5429   }
5430   PetscFunctionReturn(PETSC_SUCCESS);
5431 }
5432 
5433 /*@
5434   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5435 
5436   Collective
5437 
5438   Input Parameters:
5439 + mat   - the matrix to transpose and complex conjugate
5440 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5441 
5442   Output Parameter:
5443 . B - the Hermitian transpose
5444 
5445   Level: intermediate
5446 
5447 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5448 @*/
5449 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5450 {
5451   PetscFunctionBegin;
5452   PetscCall(MatTranspose(mat, reuse, B));
5453 #if defined(PETSC_USE_COMPLEX)
5454   PetscCall(MatConjugate(*B));
5455 #endif
5456   PetscFunctionReturn(PETSC_SUCCESS);
5457 }
5458 
5459 /*@
5460   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5461 
5462   Collective
5463 
5464   Input Parameters:
5465 + A   - the matrix to test
5466 . B   - the matrix to test against, this can equal the first parameter
5467 - tol - tolerance, differences between entries smaller than this are counted as zero
5468 
5469   Output Parameter:
5470 . flg - the result
5471 
5472   Level: intermediate
5473 
5474   Notes:
5475   Only available for `MATAIJ` matrices.
5476 
5477   The sequential algorithm
5478   has a running time of the order of the number of nonzeros; the parallel
5479   test involves parallel copies of the block off-diagonal parts of the matrix.
5480 
5481 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5482 @*/
5483 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5484 {
5485   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5486 
5487   PetscFunctionBegin;
5488   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5489   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5490   PetscAssertPointer(flg, 4);
5491   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5492   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5493   if (f && g) {
5494     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5495     PetscCall((*f)(A, B, tol, flg));
5496   }
5497   PetscFunctionReturn(PETSC_SUCCESS);
5498 }
5499 
5500 /*@
5501   MatPermute - Creates a new matrix with rows and columns permuted from the
5502   original.
5503 
5504   Collective
5505 
5506   Input Parameters:
5507 + mat - the matrix to permute
5508 . row - row permutation, each processor supplies only the permutation for its rows
5509 - col - column permutation, each processor supplies only the permutation for its columns
5510 
5511   Output Parameter:
5512 . B - the permuted matrix
5513 
5514   Level: advanced
5515 
5516   Note:
5517   The index sets map from row/col of permuted matrix to row/col of original matrix.
5518   The index sets should be on the same communicator as mat and have the same local sizes.
5519 
5520   Developer Note:
5521   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5522   exploit the fact that row and col are permutations, consider implementing the
5523   more general `MatCreateSubMatrix()` instead.
5524 
5525 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5526 @*/
5527 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5528 {
5529   PetscFunctionBegin;
5530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5531   PetscValidType(mat, 1);
5532   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5533   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5534   PetscAssertPointer(B, 4);
5535   PetscCheckSameComm(mat, 1, row, 2);
5536   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5537   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5538   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5539   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5540   MatCheckPreallocated(mat, 1);
5541 
5542   if (mat->ops->permute) {
5543     PetscUseTypeMethod(mat, permute, row, col, B);
5544     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5545   } else {
5546     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5547   }
5548   PetscFunctionReturn(PETSC_SUCCESS);
5549 }
5550 
5551 /*@
5552   MatEqual - Compares two matrices.
5553 
5554   Collective
5555 
5556   Input Parameters:
5557 + A - the first matrix
5558 - B - the second matrix
5559 
5560   Output Parameter:
5561 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5562 
5563   Level: intermediate
5564 
5565 .seealso: [](ch_matrices), `Mat`
5566 @*/
5567 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5568 {
5569   PetscFunctionBegin;
5570   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5571   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5572   PetscValidType(A, 1);
5573   PetscValidType(B, 2);
5574   PetscAssertPointer(flg, 3);
5575   PetscCheckSameComm(A, 1, B, 2);
5576   MatCheckPreallocated(A, 1);
5577   MatCheckPreallocated(B, 2);
5578   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5579   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5580   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,
5581              B->cmap->N);
5582   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5583     PetscUseTypeMethod(A, equal, B, flg);
5584   } else {
5585     PetscCall(MatMultEqual(A, B, 10, flg));
5586   }
5587   PetscFunctionReturn(PETSC_SUCCESS);
5588 }
5589 
5590 /*@
5591   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5592   matrices that are stored as vectors.  Either of the two scaling
5593   matrices can be `NULL`.
5594 
5595   Collective
5596 
5597   Input Parameters:
5598 + mat - the matrix to be scaled
5599 . l   - the left scaling vector (or `NULL`)
5600 - r   - the right scaling vector (or `NULL`)
5601 
5602   Level: intermediate
5603 
5604   Note:
5605   `MatDiagonalScale()` computes $A = LAR$, where
5606   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5607   The L scales the rows of the matrix, the R scales the columns of the matrix.
5608 
5609 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5610 @*/
5611 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5612 {
5613   PetscFunctionBegin;
5614   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5615   PetscValidType(mat, 1);
5616   if (l) {
5617     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5618     PetscCheckSameComm(mat, 1, l, 2);
5619   }
5620   if (r) {
5621     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5622     PetscCheckSameComm(mat, 1, r, 3);
5623   }
5624   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5625   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5626   MatCheckPreallocated(mat, 1);
5627   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5628 
5629   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5630   PetscUseTypeMethod(mat, diagonalscale, l, r);
5631   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5632   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5633   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5634   PetscFunctionReturn(PETSC_SUCCESS);
5635 }
5636 
5637 /*@
5638   MatScale - Scales all elements of a matrix by a given number.
5639 
5640   Logically Collective
5641 
5642   Input Parameters:
5643 + mat - the matrix to be scaled
5644 - a   - the scaling value
5645 
5646   Level: intermediate
5647 
5648 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5649 @*/
5650 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5651 {
5652   PetscFunctionBegin;
5653   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5654   PetscValidType(mat, 1);
5655   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5656   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5657   PetscValidLogicalCollectiveScalar(mat, a, 2);
5658   MatCheckPreallocated(mat, 1);
5659 
5660   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5661   if (a != (PetscScalar)1.0) {
5662     PetscUseTypeMethod(mat, scale, a);
5663     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5664   }
5665   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5666   PetscFunctionReturn(PETSC_SUCCESS);
5667 }
5668 
5669 /*@
5670   MatNorm - Calculates various norms of a matrix.
5671 
5672   Collective
5673 
5674   Input Parameters:
5675 + mat  - the matrix
5676 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5677 
5678   Output Parameter:
5679 . nrm - the resulting norm
5680 
5681   Level: intermediate
5682 
5683 .seealso: [](ch_matrices), `Mat`
5684 @*/
5685 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5686 {
5687   PetscFunctionBegin;
5688   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5689   PetscValidType(mat, 1);
5690   PetscAssertPointer(nrm, 3);
5691 
5692   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5693   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5694   MatCheckPreallocated(mat, 1);
5695 
5696   PetscUseTypeMethod(mat, norm, type, nrm);
5697   PetscFunctionReturn(PETSC_SUCCESS);
5698 }
5699 
5700 /*
5701      This variable is used to prevent counting of MatAssemblyBegin() that
5702    are called from within a MatAssemblyEnd().
5703 */
5704 static PetscInt MatAssemblyEnd_InUse = 0;
5705 /*@
5706   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5707   be called after completing all calls to `MatSetValues()`.
5708 
5709   Collective
5710 
5711   Input Parameters:
5712 + mat  - the matrix
5713 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5714 
5715   Level: beginner
5716 
5717   Notes:
5718   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5719   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5720 
5721   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5722   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5723   using the matrix.
5724 
5725   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5726   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
5727   a global collective operation requiring all processes that share the matrix.
5728 
5729   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5730   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5731   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5732 
5733 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5734 @*/
5735 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5736 {
5737   PetscFunctionBegin;
5738   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5739   PetscValidType(mat, 1);
5740   MatCheckPreallocated(mat, 1);
5741   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5742   if (mat->assembled) {
5743     mat->was_assembled = PETSC_TRUE;
5744     mat->assembled     = PETSC_FALSE;
5745   }
5746 
5747   if (!MatAssemblyEnd_InUse) {
5748     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5749     PetscTryTypeMethod(mat, assemblybegin, type);
5750     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5751   } else PetscTryTypeMethod(mat, assemblybegin, type);
5752   PetscFunctionReturn(PETSC_SUCCESS);
5753 }
5754 
5755 /*@
5756   MatAssembled - Indicates if a matrix has been assembled and is ready for
5757   use; for example, in matrix-vector product.
5758 
5759   Not Collective
5760 
5761   Input Parameter:
5762 . mat - the matrix
5763 
5764   Output Parameter:
5765 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5766 
5767   Level: advanced
5768 
5769 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5770 @*/
5771 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5772 {
5773   PetscFunctionBegin;
5774   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5775   PetscAssertPointer(assembled, 2);
5776   *assembled = mat->assembled;
5777   PetscFunctionReturn(PETSC_SUCCESS);
5778 }
5779 
5780 /*@
5781   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5782   be called after `MatAssemblyBegin()`.
5783 
5784   Collective
5785 
5786   Input Parameters:
5787 + mat  - the matrix
5788 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5789 
5790   Options Database Keys:
5791 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5792 . -mat_view ::ascii_info_detail      - Prints more detailed info
5793 . -mat_view                          - Prints matrix in ASCII format
5794 . -mat_view ::ascii_matlab           - Prints matrix in MATLAB format
5795 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5796 . -display <name>                    - Sets display name (default is host)
5797 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5798 . -mat_view socket                   - Sends matrix to socket, can be accessed from MATLAB (See [Using MATLAB with PETSc](ch_matlab))
5799 . -viewer_socket_machine <machine>   - Machine to use for socket
5800 . -viewer_socket_port <port>         - Port number to use for socket
5801 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5802 
5803   Level: beginner
5804 
5805 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5806 @*/
5807 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5808 {
5809   static PetscInt inassm = 0;
5810   PetscBool       flg    = PETSC_FALSE;
5811 
5812   PetscFunctionBegin;
5813   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5814   PetscValidType(mat, 1);
5815 
5816   inassm++;
5817   MatAssemblyEnd_InUse++;
5818   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5819     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5820     PetscTryTypeMethod(mat, assemblyend, type);
5821     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5822   } else PetscTryTypeMethod(mat, assemblyend, type);
5823 
5824   /* Flush assembly is not a true assembly */
5825   if (type != MAT_FLUSH_ASSEMBLY) {
5826     if (mat->num_ass) {
5827       if (!mat->symmetry_eternal) {
5828         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5829         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5830       }
5831       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5832       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5833     }
5834     mat->num_ass++;
5835     mat->assembled        = PETSC_TRUE;
5836     mat->ass_nonzerostate = mat->nonzerostate;
5837   }
5838 
5839   mat->insertmode = NOT_SET_VALUES;
5840   MatAssemblyEnd_InUse--;
5841   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5842   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5843     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5844 
5845     if (mat->checksymmetryonassembly) {
5846       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5847       if (flg) {
5848         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5849       } else {
5850         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5851       }
5852     }
5853     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5854   }
5855   inassm--;
5856   PetscFunctionReturn(PETSC_SUCCESS);
5857 }
5858 
5859 // PetscClangLinter pragma disable: -fdoc-section-header-unknown
5860 /*@
5861   MatSetOption - Sets a parameter option for a matrix. Some options
5862   may be specific to certain storage formats.  Some options
5863   determine how values will be inserted (or added). Sorted,
5864   row-oriented input will generally assemble the fastest. The default
5865   is row-oriented.
5866 
5867   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5868 
5869   Input Parameters:
5870 + mat - the matrix
5871 . op  - the option, one of those listed below (and possibly others),
5872 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5873 
5874   Options Describing Matrix Structure:
5875 + `MAT_SPD`                         - symmetric positive definite
5876 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5877 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5878 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5879 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5880 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5881 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5882 
5883    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5884    do not need to be computed (usually at a high cost)
5885 
5886    Options For Use with `MatSetValues()`:
5887    Insert a logically dense subblock, which can be
5888 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5889 
5890    These options reflect the data you pass in with `MatSetValues()`; it has
5891    nothing to do with how the data is stored internally in the matrix
5892    data structure.
5893 
5894    When (re)assembling a matrix, we can restrict the input for
5895    efficiency/debugging purposes.  These options include
5896 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5897 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5898 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5899 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5900 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5901 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5902         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5903         performance for very large process counts.
5904 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5905         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5906         functions, instead sending only neighbor messages.
5907 
5908   Level: intermediate
5909 
5910   Notes:
5911   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5912 
5913   Some options are relevant only for particular matrix types and
5914   are thus ignored by others.  Other options are not supported by
5915   certain matrix types and will generate an error message if set.
5916 
5917   If using Fortran to compute a matrix, one may need to
5918   use the column-oriented option (or convert to the row-oriented
5919   format).
5920 
5921   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5922   that would generate a new entry in the nonzero structure is instead
5923   ignored.  Thus, if memory has not already been allocated for this particular
5924   data, then the insertion is ignored. For dense matrices, in which
5925   the entire array is allocated, no entries are ever ignored.
5926   Set after the first `MatAssemblyEnd()`. If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5927 
5928   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5929   that would generate a new entry in the nonzero structure instead produces
5930   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
5931 
5932   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5933   that would generate a new entry that has not been preallocated will
5934   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5935   only.) This is a useful flag when debugging matrix memory preallocation.
5936   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5937 
5938   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5939   other processors should be dropped, rather than stashed.
5940   This is useful if you know that the "owning" processor is also
5941   always generating the correct matrix entries, so that PETSc need
5942   not transfer duplicate entries generated on another processor.
5943 
5944   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5945   searches during matrix assembly. When this flag is set, the hash table
5946   is created during the first matrix assembly. This hash table is
5947   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5948   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5949   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5950   supported by `MATMPIBAIJ` format only.
5951 
5952   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5953   are kept in the nonzero structure
5954 
5955   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5956   a zero location in the matrix
5957 
5958   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5959 
5960   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5961   zero row routines and thus improves performance for very large process counts.
5962 
5963   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5964   part of the matrix (since they should match the upper triangular part).
5965 
5966   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5967   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5968   with finite difference schemes with non-periodic boundary conditions.
5969 
5970   Developer Note:
5971   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5972   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURALLY_SYMMETRIC` or `MAT_SPD` would need to be changed back
5973   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5974   not changed.
5975 
5976 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5977 @*/
5978 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5979 {
5980   PetscFunctionBegin;
5981   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5982   if (op > 0) {
5983     PetscValidLogicalCollectiveEnum(mat, op, 2);
5984     PetscValidLogicalCollectiveBool(mat, flg, 3);
5985   }
5986 
5987   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);
5988 
5989   switch (op) {
5990   case MAT_FORCE_DIAGONAL_ENTRIES:
5991     mat->force_diagonals = flg;
5992     PetscFunctionReturn(PETSC_SUCCESS);
5993   case MAT_NO_OFF_PROC_ENTRIES:
5994     mat->nooffprocentries = flg;
5995     PetscFunctionReturn(PETSC_SUCCESS);
5996   case MAT_SUBSET_OFF_PROC_ENTRIES:
5997     mat->assembly_subset = flg;
5998     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5999 #if !defined(PETSC_HAVE_MPIUNI)
6000       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
6001 #endif
6002       mat->stash.first_assembly_done = PETSC_FALSE;
6003     }
6004     PetscFunctionReturn(PETSC_SUCCESS);
6005   case MAT_NO_OFF_PROC_ZERO_ROWS:
6006     mat->nooffproczerorows = flg;
6007     PetscFunctionReturn(PETSC_SUCCESS);
6008   case MAT_SPD:
6009     if (flg) {
6010       mat->spd                    = PETSC_BOOL3_TRUE;
6011       mat->symmetric              = PETSC_BOOL3_TRUE;
6012       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6013     } else {
6014       mat->spd = PETSC_BOOL3_FALSE;
6015     }
6016     break;
6017   case MAT_SYMMETRIC:
6018     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6019     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6020 #if !defined(PETSC_USE_COMPLEX)
6021     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6022 #endif
6023     break;
6024   case MAT_HERMITIAN:
6025     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6026     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
6027 #if !defined(PETSC_USE_COMPLEX)
6028     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6029 #endif
6030     break;
6031   case MAT_STRUCTURALLY_SYMMETRIC:
6032     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
6033     break;
6034   case MAT_SYMMETRY_ETERNAL:
6035     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");
6036     mat->symmetry_eternal = flg;
6037     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
6038     break;
6039   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6040     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");
6041     mat->structural_symmetry_eternal = flg;
6042     break;
6043   case MAT_SPD_ETERNAL:
6044     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");
6045     mat->spd_eternal = flg;
6046     if (flg) {
6047       mat->structural_symmetry_eternal = PETSC_TRUE;
6048       mat->symmetry_eternal            = PETSC_TRUE;
6049     }
6050     break;
6051   case MAT_STRUCTURE_ONLY:
6052     mat->structure_only = flg;
6053     break;
6054   case MAT_SORTED_FULL:
6055     mat->sortedfull = flg;
6056     break;
6057   default:
6058     break;
6059   }
6060   PetscTryTypeMethod(mat, setoption, op, flg);
6061   PetscFunctionReturn(PETSC_SUCCESS);
6062 }
6063 
6064 /*@
6065   MatGetOption - Gets a parameter option that has been set for a matrix.
6066 
6067   Logically Collective
6068 
6069   Input Parameters:
6070 + mat - the matrix
6071 - op  - the option, this only responds to certain options, check the code for which ones
6072 
6073   Output Parameter:
6074 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6075 
6076   Level: intermediate
6077 
6078   Notes:
6079   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6080 
6081   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6082   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6083 
6084 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6085     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6086 @*/
6087 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6088 {
6089   PetscFunctionBegin;
6090   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6091   PetscValidType(mat, 1);
6092 
6093   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);
6094   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()");
6095 
6096   switch (op) {
6097   case MAT_NO_OFF_PROC_ENTRIES:
6098     *flg = mat->nooffprocentries;
6099     break;
6100   case MAT_NO_OFF_PROC_ZERO_ROWS:
6101     *flg = mat->nooffproczerorows;
6102     break;
6103   case MAT_SYMMETRIC:
6104     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6105     break;
6106   case MAT_HERMITIAN:
6107     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6108     break;
6109   case MAT_STRUCTURALLY_SYMMETRIC:
6110     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6111     break;
6112   case MAT_SPD:
6113     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6114     break;
6115   case MAT_SYMMETRY_ETERNAL:
6116     *flg = mat->symmetry_eternal;
6117     break;
6118   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6119     *flg = mat->symmetry_eternal;
6120     break;
6121   default:
6122     break;
6123   }
6124   PetscFunctionReturn(PETSC_SUCCESS);
6125 }
6126 
6127 /*@
6128   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6129   this routine retains the old nonzero structure.
6130 
6131   Logically Collective
6132 
6133   Input Parameter:
6134 . mat - the matrix
6135 
6136   Level: intermediate
6137 
6138   Note:
6139   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.
6140   See the Performance chapter of the users manual for information on preallocating matrices.
6141 
6142 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6143 @*/
6144 PetscErrorCode MatZeroEntries(Mat mat)
6145 {
6146   PetscFunctionBegin;
6147   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6148   PetscValidType(mat, 1);
6149   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6150   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");
6151   MatCheckPreallocated(mat, 1);
6152 
6153   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6154   PetscUseTypeMethod(mat, zeroentries);
6155   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6156   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6157   PetscFunctionReturn(PETSC_SUCCESS);
6158 }
6159 
6160 /*@
6161   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6162   of a set of rows and columns of a matrix.
6163 
6164   Collective
6165 
6166   Input Parameters:
6167 + mat     - the matrix
6168 . numRows - the number of rows/columns to zero
6169 . rows    - the global row indices
6170 . diag    - value put in the diagonal of the eliminated rows
6171 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6172 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6173 
6174   Level: intermediate
6175 
6176   Notes:
6177   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6178 
6179   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6180   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
6181 
6182   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6183   Krylov method to take advantage of the known solution on the zeroed rows.
6184 
6185   For the parallel case, all processes that share the matrix (i.e.,
6186   those in the communicator used for matrix creation) MUST call this
6187   routine, regardless of whether any rows being zeroed are owned by
6188   them.
6189 
6190   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6191 
6192   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6193   list only rows local to itself).
6194 
6195   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6196 
6197 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6198           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6199 @*/
6200 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6201 {
6202   PetscFunctionBegin;
6203   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6204   PetscValidType(mat, 1);
6205   if (numRows) PetscAssertPointer(rows, 3);
6206   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6207   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6208   MatCheckPreallocated(mat, 1);
6209 
6210   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6211   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6212   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6213   PetscFunctionReturn(PETSC_SUCCESS);
6214 }
6215 
6216 /*@
6217   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6218   of a set of rows and columns of a matrix.
6219 
6220   Collective
6221 
6222   Input Parameters:
6223 + mat  - the matrix
6224 . is   - the rows to zero
6225 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6226 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6227 - b    - optional vector of right hand side, that will be adjusted by provided solution
6228 
6229   Level: intermediate
6230 
6231   Note:
6232   See `MatZeroRowsColumns()` for details on how this routine operates.
6233 
6234 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6235           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6236 @*/
6237 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6238 {
6239   PetscInt        numRows;
6240   const PetscInt *rows;
6241 
6242   PetscFunctionBegin;
6243   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6244   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6245   PetscValidType(mat, 1);
6246   PetscValidType(is, 2);
6247   PetscCall(ISGetLocalSize(is, &numRows));
6248   PetscCall(ISGetIndices(is, &rows));
6249   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6250   PetscCall(ISRestoreIndices(is, &rows));
6251   PetscFunctionReturn(PETSC_SUCCESS);
6252 }
6253 
6254 /*@
6255   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6256   of a set of rows of a matrix.
6257 
6258   Collective
6259 
6260   Input Parameters:
6261 + mat     - the matrix
6262 . numRows - the number of rows to zero
6263 . rows    - the global row indices
6264 . diag    - value put in the diagonal of the zeroed rows
6265 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6266 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6267 
6268   Level: intermediate
6269 
6270   Notes:
6271   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6272 
6273   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6274 
6275   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6276   Krylov method to take advantage of the known solution on the zeroed rows.
6277 
6278   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)
6279   from the matrix.
6280 
6281   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6282   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
6283   formats this does not alter the nonzero structure.
6284 
6285   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6286   of the matrix is not changed the values are
6287   merely zeroed.
6288 
6289   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6290   formats can optionally remove the main diagonal entry from the
6291   nonzero structure as well, by passing 0.0 as the final argument).
6292 
6293   For the parallel case, all processes that share the matrix (i.e.,
6294   those in the communicator used for matrix creation) MUST call this
6295   routine, regardless of whether any rows being zeroed are owned by
6296   them.
6297 
6298   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6299   list only rows local to itself).
6300 
6301   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6302   owns that are to be zeroed. This saves a global synchronization in the implementation.
6303 
6304 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6305           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6306 @*/
6307 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6308 {
6309   PetscFunctionBegin;
6310   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6311   PetscValidType(mat, 1);
6312   if (numRows) PetscAssertPointer(rows, 3);
6313   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6314   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6315   MatCheckPreallocated(mat, 1);
6316 
6317   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6318   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6319   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6320   PetscFunctionReturn(PETSC_SUCCESS);
6321 }
6322 
6323 /*@
6324   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6325   of a set of rows of a matrix.
6326 
6327   Collective
6328 
6329   Input Parameters:
6330 + mat  - the matrix
6331 . is   - index set of rows to remove (if `NULL` then no row is removed)
6332 . diag - value put in all diagonals of eliminated rows
6333 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6334 - b    - optional vector of right hand side, that will be adjusted by provided solution
6335 
6336   Level: intermediate
6337 
6338   Note:
6339   See `MatZeroRows()` for details on how this routine operates.
6340 
6341 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6342           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6343 @*/
6344 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6345 {
6346   PetscInt        numRows = 0;
6347   const PetscInt *rows    = NULL;
6348 
6349   PetscFunctionBegin;
6350   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6351   PetscValidType(mat, 1);
6352   if (is) {
6353     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6354     PetscCall(ISGetLocalSize(is, &numRows));
6355     PetscCall(ISGetIndices(is, &rows));
6356   }
6357   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6358   if (is) PetscCall(ISRestoreIndices(is, &rows));
6359   PetscFunctionReturn(PETSC_SUCCESS);
6360 }
6361 
6362 /*@
6363   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6364   of a set of rows of a matrix. These rows must be local to the process.
6365 
6366   Collective
6367 
6368   Input Parameters:
6369 + mat     - the matrix
6370 . numRows - the number of rows to remove
6371 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6372 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6373 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6374 - b       - optional vector of right hand side, that will be adjusted by provided solution
6375 
6376   Level: intermediate
6377 
6378   Notes:
6379   See `MatZeroRows()` for details on how this routine operates.
6380 
6381   The grid coordinates are across the entire grid, not just the local portion
6382 
6383   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6384   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6385   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6386   `DM_BOUNDARY_PERIODIC` boundary type.
6387 
6388   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
6389   a single value per point) you can skip filling those indices.
6390 
6391   Fortran Note:
6392   `idxm` and `idxn` should be declared as
6393 $     MatStencil idxm(4, m)
6394   and the values inserted using
6395 .vb
6396     idxm(MatStencil_i, 1) = i
6397     idxm(MatStencil_j, 1) = j
6398     idxm(MatStencil_k, 1) = k
6399     idxm(MatStencil_c, 1) = c
6400    etc
6401 .ve
6402 
6403 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6404           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6405 @*/
6406 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6407 {
6408   PetscInt  dim    = mat->stencil.dim;
6409   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6410   PetscInt *dims   = mat->stencil.dims + 1;
6411   PetscInt *starts = mat->stencil.starts;
6412   PetscInt *dxm    = (PetscInt *)rows;
6413   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6414 
6415   PetscFunctionBegin;
6416   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6417   PetscValidType(mat, 1);
6418   if (numRows) PetscAssertPointer(rows, 3);
6419 
6420   PetscCall(PetscMalloc1(numRows, &jdxm));
6421   for (i = 0; i < numRows; ++i) {
6422     /* Skip unused dimensions (they are ordered k, j, i, c) */
6423     for (j = 0; j < 3 - sdim; ++j) dxm++;
6424     /* Local index in X dir */
6425     tmp = *dxm++ - starts[0];
6426     /* Loop over remaining dimensions */
6427     for (j = 0; j < dim - 1; ++j) {
6428       /* If nonlocal, set index to be negative */
6429       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6430       /* Update local index */
6431       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6432     }
6433     /* Skip component slot if necessary */
6434     if (mat->stencil.noc) dxm++;
6435     /* Local row number */
6436     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6437   }
6438   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6439   PetscCall(PetscFree(jdxm));
6440   PetscFunctionReturn(PETSC_SUCCESS);
6441 }
6442 
6443 /*@
6444   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6445   of a set of rows and columns of a matrix.
6446 
6447   Collective
6448 
6449   Input Parameters:
6450 + mat     - the matrix
6451 . numRows - the number of rows/columns to remove
6452 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6453 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6454 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6455 - b       - optional vector of right hand side, that will be adjusted by provided solution
6456 
6457   Level: intermediate
6458 
6459   Notes:
6460   See `MatZeroRowsColumns()` for details on how this routine operates.
6461 
6462   The grid coordinates are across the entire grid, not just the local portion
6463 
6464   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6465   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6466   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6467   `DM_BOUNDARY_PERIODIC` boundary type.
6468 
6469   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
6470   a single value per point) you can skip filling those indices.
6471 
6472   Fortran Note:
6473   `idxm` and `idxn` should be declared as
6474 $     MatStencil idxm(4, m)
6475   and the values inserted using
6476 .vb
6477     idxm(MatStencil_i, 1) = i
6478     idxm(MatStencil_j, 1) = j
6479     idxm(MatStencil_k, 1) = k
6480     idxm(MatStencil_c, 1) = c
6481     etc
6482 .ve
6483 
6484 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6485           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6486 @*/
6487 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6488 {
6489   PetscInt  dim    = mat->stencil.dim;
6490   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6491   PetscInt *dims   = mat->stencil.dims + 1;
6492   PetscInt *starts = mat->stencil.starts;
6493   PetscInt *dxm    = (PetscInt *)rows;
6494   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6495 
6496   PetscFunctionBegin;
6497   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6498   PetscValidType(mat, 1);
6499   if (numRows) PetscAssertPointer(rows, 3);
6500 
6501   PetscCall(PetscMalloc1(numRows, &jdxm));
6502   for (i = 0; i < numRows; ++i) {
6503     /* Skip unused dimensions (they are ordered k, j, i, c) */
6504     for (j = 0; j < 3 - sdim; ++j) dxm++;
6505     /* Local index in X dir */
6506     tmp = *dxm++ - starts[0];
6507     /* Loop over remaining dimensions */
6508     for (j = 0; j < dim - 1; ++j) {
6509       /* If nonlocal, set index to be negative */
6510       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6511       /* Update local index */
6512       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6513     }
6514     /* Skip component slot if necessary */
6515     if (mat->stencil.noc) dxm++;
6516     /* Local row number */
6517     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6518   }
6519   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6520   PetscCall(PetscFree(jdxm));
6521   PetscFunctionReturn(PETSC_SUCCESS);
6522 }
6523 
6524 /*@C
6525   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6526   of a set of rows of a matrix; using local numbering of rows.
6527 
6528   Collective
6529 
6530   Input Parameters:
6531 + mat     - the matrix
6532 . numRows - the number of rows to remove
6533 . rows    - the local row indices
6534 . diag    - value put in all diagonals of eliminated rows
6535 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6536 - b       - optional vector of right hand side, that will be adjusted by provided solution
6537 
6538   Level: intermediate
6539 
6540   Notes:
6541   Before calling `MatZeroRowsLocal()`, the user must first set the
6542   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6543 
6544   See `MatZeroRows()` for details on how this routine operates.
6545 
6546 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6547           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6548 @*/
6549 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6550 {
6551   PetscFunctionBegin;
6552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6553   PetscValidType(mat, 1);
6554   if (numRows) PetscAssertPointer(rows, 3);
6555   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6556   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6557   MatCheckPreallocated(mat, 1);
6558 
6559   if (mat->ops->zerorowslocal) {
6560     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6561   } else {
6562     IS              is, newis;
6563     const PetscInt *newRows;
6564 
6565     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6566     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6567     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6568     PetscCall(ISGetIndices(newis, &newRows));
6569     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6570     PetscCall(ISRestoreIndices(newis, &newRows));
6571     PetscCall(ISDestroy(&newis));
6572     PetscCall(ISDestroy(&is));
6573   }
6574   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6575   PetscFunctionReturn(PETSC_SUCCESS);
6576 }
6577 
6578 /*@
6579   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6580   of a set of rows of a matrix; using local numbering of rows.
6581 
6582   Collective
6583 
6584   Input Parameters:
6585 + mat  - the matrix
6586 . is   - index set of rows to remove
6587 . diag - value put in all diagonals of eliminated rows
6588 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6589 - b    - optional vector of right hand side, that will be adjusted by provided solution
6590 
6591   Level: intermediate
6592 
6593   Notes:
6594   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6595   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6596 
6597   See `MatZeroRows()` for details on how this routine operates.
6598 
6599 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6600           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6601 @*/
6602 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6603 {
6604   PetscInt        numRows;
6605   const PetscInt *rows;
6606 
6607   PetscFunctionBegin;
6608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6609   PetscValidType(mat, 1);
6610   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6611   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6612   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6613   MatCheckPreallocated(mat, 1);
6614 
6615   PetscCall(ISGetLocalSize(is, &numRows));
6616   PetscCall(ISGetIndices(is, &rows));
6617   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6618   PetscCall(ISRestoreIndices(is, &rows));
6619   PetscFunctionReturn(PETSC_SUCCESS);
6620 }
6621 
6622 /*@
6623   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6624   of a set of rows and columns of a matrix; using local numbering of rows.
6625 
6626   Collective
6627 
6628   Input Parameters:
6629 + mat     - the matrix
6630 . numRows - the number of rows to remove
6631 . rows    - the global row indices
6632 . diag    - value put in all diagonals of eliminated rows
6633 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6634 - b       - optional vector of right hand side, that will be adjusted by provided solution
6635 
6636   Level: intermediate
6637 
6638   Notes:
6639   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6640   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6641 
6642   See `MatZeroRowsColumns()` for details on how this routine operates.
6643 
6644 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6645           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6646 @*/
6647 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6648 {
6649   IS              is, newis;
6650   const PetscInt *newRows;
6651 
6652   PetscFunctionBegin;
6653   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6654   PetscValidType(mat, 1);
6655   if (numRows) PetscAssertPointer(rows, 3);
6656   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6657   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6658   MatCheckPreallocated(mat, 1);
6659 
6660   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6661   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6662   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6663   PetscCall(ISGetIndices(newis, &newRows));
6664   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6665   PetscCall(ISRestoreIndices(newis, &newRows));
6666   PetscCall(ISDestroy(&newis));
6667   PetscCall(ISDestroy(&is));
6668   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6669   PetscFunctionReturn(PETSC_SUCCESS);
6670 }
6671 
6672 /*@
6673   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6674   of a set of rows and columns of a matrix; using local numbering of rows.
6675 
6676   Collective
6677 
6678   Input Parameters:
6679 + mat  - the matrix
6680 . is   - index set of rows to remove
6681 . diag - value put in all diagonals of eliminated rows
6682 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6683 - b    - optional vector of right hand side, that will be adjusted by provided solution
6684 
6685   Level: intermediate
6686 
6687   Notes:
6688   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6689   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6690 
6691   See `MatZeroRowsColumns()` for details on how this routine operates.
6692 
6693 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6694           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6695 @*/
6696 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6697 {
6698   PetscInt        numRows;
6699   const PetscInt *rows;
6700 
6701   PetscFunctionBegin;
6702   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6703   PetscValidType(mat, 1);
6704   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6705   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6706   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6707   MatCheckPreallocated(mat, 1);
6708 
6709   PetscCall(ISGetLocalSize(is, &numRows));
6710   PetscCall(ISGetIndices(is, &rows));
6711   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6712   PetscCall(ISRestoreIndices(is, &rows));
6713   PetscFunctionReturn(PETSC_SUCCESS);
6714 }
6715 
6716 /*@C
6717   MatGetSize - Returns the numbers of rows and columns in a matrix.
6718 
6719   Not Collective
6720 
6721   Input Parameter:
6722 . mat - the matrix
6723 
6724   Output Parameters:
6725 + m - the number of global rows
6726 - n - the number of global columns
6727 
6728   Level: beginner
6729 
6730   Note:
6731   Both output parameters can be `NULL` on input.
6732 
6733 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6734 @*/
6735 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6736 {
6737   PetscFunctionBegin;
6738   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6739   if (m) *m = mat->rmap->N;
6740   if (n) *n = mat->cmap->N;
6741   PetscFunctionReturn(PETSC_SUCCESS);
6742 }
6743 
6744 /*@C
6745   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6746   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6747 
6748   Not Collective
6749 
6750   Input Parameter:
6751 . mat - the matrix
6752 
6753   Output Parameters:
6754 + m - the number of local rows, use `NULL` to not obtain this value
6755 - n - the number of local columns, use `NULL` to not obtain this value
6756 
6757   Level: beginner
6758 
6759 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6760 @*/
6761 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6762 {
6763   PetscFunctionBegin;
6764   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6765   if (m) PetscAssertPointer(m, 2);
6766   if (n) PetscAssertPointer(n, 3);
6767   if (m) *m = mat->rmap->n;
6768   if (n) *n = mat->cmap->n;
6769   PetscFunctionReturn(PETSC_SUCCESS);
6770 }
6771 
6772 /*@C
6773   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a
6774   vector one multiplies this matrix by that are owned by this processor.
6775 
6776   Not Collective, unless matrix has not been allocated, then collective
6777 
6778   Input Parameter:
6779 . mat - the matrix
6780 
6781   Output Parameters:
6782 + m - the global index of the first local column, use `NULL` to not obtain this value
6783 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6784 
6785   Level: developer
6786 
6787   Note:
6788   Returns the columns of the "diagonal block" for most sparse matrix formats. See [Matrix
6789   Layouts](sec_matlayout) for details on matrix layouts.
6790 
6791 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6792 @*/
6793 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6794 {
6795   PetscFunctionBegin;
6796   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6797   PetscValidType(mat, 1);
6798   if (m) PetscAssertPointer(m, 2);
6799   if (n) PetscAssertPointer(n, 3);
6800   MatCheckPreallocated(mat, 1);
6801   if (m) *m = mat->cmap->rstart;
6802   if (n) *n = mat->cmap->rend;
6803   PetscFunctionReturn(PETSC_SUCCESS);
6804 }
6805 
6806 /*@C
6807   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6808   this MPI process.
6809 
6810   Not Collective
6811 
6812   Input Parameter:
6813 . mat - the matrix
6814 
6815   Output Parameters:
6816 + m - the global index of the first local row, use `NULL` to not obtain this value
6817 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6818 
6819   Level: beginner
6820 
6821   Note:
6822   For all matrices  it returns the range of matrix rows associated with rows of a vector that
6823   would contain the result of a matrix vector product with this matrix. See [Matrix
6824   Layouts](sec_matlayout) for details on matrix layouts.
6825 
6826 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6827           `PetscLayout`
6828 @*/
6829 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6830 {
6831   PetscFunctionBegin;
6832   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6833   PetscValidType(mat, 1);
6834   if (m) PetscAssertPointer(m, 2);
6835   if (n) PetscAssertPointer(n, 3);
6836   MatCheckPreallocated(mat, 1);
6837   if (m) *m = mat->rmap->rstart;
6838   if (n) *n = mat->rmap->rend;
6839   PetscFunctionReturn(PETSC_SUCCESS);
6840 }
6841 
6842 /*@C
6843   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and
6844   `MATSCALAPACK`, returns the range of matrix rows owned by each process.
6845 
6846   Not Collective, unless matrix has not been allocated
6847 
6848   Input Parameter:
6849 . mat - the matrix
6850 
6851   Output Parameter:
6852 . ranges - start of each processors portion plus one more than the total length at the end
6853 
6854   Level: beginner
6855 
6856   Note:
6857   For all matrices  it returns the ranges of matrix rows associated with rows of a vector that
6858   would contain the result of a matrix vector product with this matrix. See [Matrix
6859   Layouts](sec_matlayout) for details on matrix layouts.
6860 
6861 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6862 @*/
6863 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6864 {
6865   PetscFunctionBegin;
6866   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6867   PetscValidType(mat, 1);
6868   MatCheckPreallocated(mat, 1);
6869   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6870   PetscFunctionReturn(PETSC_SUCCESS);
6871 }
6872 
6873 /*@C
6874   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a
6875   vector one multiplies this vector by that are owned by each processor.
6876 
6877   Not Collective, unless matrix has not been allocated
6878 
6879   Input Parameter:
6880 . mat - the matrix
6881 
6882   Output Parameter:
6883 . ranges - start of each processors portion plus one more than the total length at the end
6884 
6885   Level: beginner
6886 
6887   Note:
6888   Returns the columns of the "diagonal blocks", for most sparse matrix formats. See [Matrix
6889   Layouts](sec_matlayout) for details on matrix layouts.
6890 
6891 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6892 @*/
6893 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6894 {
6895   PetscFunctionBegin;
6896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6897   PetscValidType(mat, 1);
6898   MatCheckPreallocated(mat, 1);
6899   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6900   PetscFunctionReturn(PETSC_SUCCESS);
6901 }
6902 
6903 /*@C
6904   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets.
6905 
6906   Not Collective
6907 
6908   Input Parameter:
6909 . A - matrix
6910 
6911   Output Parameters:
6912 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6913 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6914 
6915   Level: intermediate
6916 
6917   Note:
6918   For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this corresponds to values
6919   returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and
6920   `MATSCALAPACK` the ownership is more complicated. See [Matrix Layouts](sec_matlayout) for
6921   details on matrix layouts.
6922 
6923 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6924 @*/
6925 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6926 {
6927   PetscErrorCode (*f)(Mat, IS *, IS *);
6928 
6929   PetscFunctionBegin;
6930   MatCheckPreallocated(A, 1);
6931   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6932   if (f) {
6933     PetscCall((*f)(A, rows, cols));
6934   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6935     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6936     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6937   }
6938   PetscFunctionReturn(PETSC_SUCCESS);
6939 }
6940 
6941 /*@C
6942   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6943   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6944   to complete the factorization.
6945 
6946   Collective
6947 
6948   Input Parameters:
6949 + fact - the factorized matrix obtained with `MatGetFactor()`
6950 . mat  - the matrix
6951 . row  - row permutation
6952 . col  - column permutation
6953 - info - structure containing
6954 .vb
6955       levels - number of levels of fill.
6956       expected fill - as ratio of original fill.
6957       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6958                 missing diagonal entries)
6959 .ve
6960 
6961   Level: developer
6962 
6963   Notes:
6964   See [Matrix Factorization](sec_matfactor) for additional information.
6965 
6966   Most users should employ the `KSP` interface for linear solvers
6967   instead of working directly with matrix algebra routines such as this.
6968   See, e.g., `KSPCreate()`.
6969 
6970   Uses the definition of level of fill as in Y. Saad, {cite}`saad2003`
6971 
6972   Developer Note:
6973   The Fortran interface is not autogenerated as the
6974   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6975 
6976 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6977           `MatGetOrdering()`, `MatFactorInfo`
6978 @*/
6979 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6980 {
6981   PetscFunctionBegin;
6982   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6983   PetscValidType(mat, 2);
6984   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6985   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6986   PetscAssertPointer(info, 5);
6987   PetscAssertPointer(fact, 1);
6988   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6989   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6990   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6991   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6992   MatCheckPreallocated(mat, 2);
6993 
6994   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6995   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6996   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6997   PetscFunctionReturn(PETSC_SUCCESS);
6998 }
6999 
7000 /*@C
7001   MatICCFactorSymbolic - Performs symbolic incomplete
7002   Cholesky factorization for a symmetric matrix.  Use
7003   `MatCholeskyFactorNumeric()` to complete the factorization.
7004 
7005   Collective
7006 
7007   Input Parameters:
7008 + fact - the factorized matrix obtained with `MatGetFactor()`
7009 . mat  - the matrix to be factored
7010 . perm - row and column permutation
7011 - info - structure containing
7012 .vb
7013       levels - number of levels of fill.
7014       expected fill - as ratio of original fill.
7015 .ve
7016 
7017   Level: developer
7018 
7019   Notes:
7020   Most users should employ the `KSP` interface for linear solvers
7021   instead of working directly with matrix algebra routines such as this.
7022   See, e.g., `KSPCreate()`.
7023 
7024   This uses the definition of level of fill as in Y. Saad {cite}`saad2003`
7025 
7026   Developer Note:
7027   The Fortran interface is not autogenerated as the
7028   interface definition cannot be generated correctly [due to `MatFactorInfo`]
7029 
7030 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
7031 @*/
7032 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
7033 {
7034   PetscFunctionBegin;
7035   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
7036   PetscValidType(mat, 2);
7037   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
7038   PetscAssertPointer(info, 4);
7039   PetscAssertPointer(fact, 1);
7040   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7041   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
7042   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
7043   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7044   MatCheckPreallocated(mat, 2);
7045 
7046   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7047   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
7048   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
7049   PetscFunctionReturn(PETSC_SUCCESS);
7050 }
7051 
7052 /*@C
7053   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
7054   points to an array of valid matrices, they may be reused to store the new
7055   submatrices.
7056 
7057   Collective
7058 
7059   Input Parameters:
7060 + mat   - the matrix
7061 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
7062 . irow  - index set of rows to extract
7063 . icol  - index set of columns to extract
7064 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7065 
7066   Output Parameter:
7067 . submat - the array of submatrices
7068 
7069   Level: advanced
7070 
7071   Notes:
7072   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
7073   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
7074   to extract a parallel submatrix.
7075 
7076   Some matrix types place restrictions on the row and column
7077   indices, such as that they be sorted or that they be equal to each other.
7078 
7079   The index sets may not have duplicate entries.
7080 
7081   When extracting submatrices from a parallel matrix, each processor can
7082   form a different submatrix by setting the rows and columns of its
7083   individual index sets according to the local submatrix desired.
7084 
7085   When finished using the submatrices, the user should destroy
7086   them with `MatDestroySubMatrices()`.
7087 
7088   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7089   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7090 
7091   This routine creates the matrices in submat; you should NOT create them before
7092   calling it. It also allocates the array of matrix pointers submat.
7093 
7094   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7095   request one row/column in a block, they must request all rows/columns that are in
7096   that block. For example, if the block size is 2 you cannot request just row 0 and
7097   column 0.
7098 
7099   Fortran Note:
7100   The Fortran interface is slightly different from that given below; it
7101   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7102 
7103 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7104 @*/
7105 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7106 {
7107   PetscInt  i;
7108   PetscBool eq;
7109 
7110   PetscFunctionBegin;
7111   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7112   PetscValidType(mat, 1);
7113   if (n) {
7114     PetscAssertPointer(irow, 3);
7115     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7116     PetscAssertPointer(icol, 4);
7117     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7118   }
7119   PetscAssertPointer(submat, 6);
7120   if (n && scall == MAT_REUSE_MATRIX) {
7121     PetscAssertPointer(*submat, 6);
7122     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7123   }
7124   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7125   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7126   MatCheckPreallocated(mat, 1);
7127   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7128   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7129   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7130   for (i = 0; i < n; i++) {
7131     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7132     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7133     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7134 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7135     if (mat->boundtocpu && mat->bindingpropagates) {
7136       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7137       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7138     }
7139 #endif
7140   }
7141   PetscFunctionReturn(PETSC_SUCCESS);
7142 }
7143 
7144 /*@C
7145   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7146 
7147   Collective
7148 
7149   Input Parameters:
7150 + mat   - the matrix
7151 . n     - the number of submatrixes to be extracted
7152 . irow  - index set of rows to extract
7153 . icol  - index set of columns to extract
7154 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7155 
7156   Output Parameter:
7157 . submat - the array of submatrices
7158 
7159   Level: advanced
7160 
7161   Note:
7162   This is used by `PCGASM`
7163 
7164 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7165 @*/
7166 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7167 {
7168   PetscInt  i;
7169   PetscBool eq;
7170 
7171   PetscFunctionBegin;
7172   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7173   PetscValidType(mat, 1);
7174   if (n) {
7175     PetscAssertPointer(irow, 3);
7176     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7177     PetscAssertPointer(icol, 4);
7178     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7179   }
7180   PetscAssertPointer(submat, 6);
7181   if (n && scall == MAT_REUSE_MATRIX) {
7182     PetscAssertPointer(*submat, 6);
7183     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7184   }
7185   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7186   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7187   MatCheckPreallocated(mat, 1);
7188 
7189   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7190   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7191   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7192   for (i = 0; i < n; i++) {
7193     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7194     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7195   }
7196   PetscFunctionReturn(PETSC_SUCCESS);
7197 }
7198 
7199 /*@C
7200   MatDestroyMatrices - Destroys an array of matrices.
7201 
7202   Collective
7203 
7204   Input Parameters:
7205 + n   - the number of local matrices
7206 - mat - the matrices (this is a pointer to the array of matrices)
7207 
7208   Level: advanced
7209 
7210   Note:
7211   Frees not only the matrices, but also the array that contains the matrices
7212 
7213   Fortran Note:
7214   This does not free the array.
7215 
7216 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7217 @*/
7218 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7219 {
7220   PetscInt i;
7221 
7222   PetscFunctionBegin;
7223   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7224   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7225   PetscAssertPointer(mat, 2);
7226 
7227   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7228 
7229   /* memory is allocated even if n = 0 */
7230   PetscCall(PetscFree(*mat));
7231   PetscFunctionReturn(PETSC_SUCCESS);
7232 }
7233 
7234 /*@C
7235   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7236 
7237   Collective
7238 
7239   Input Parameters:
7240 + n   - the number of local matrices
7241 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7242                        sequence of `MatCreateSubMatrices()`)
7243 
7244   Level: advanced
7245 
7246   Note:
7247   Frees not only the matrices, but also the array that contains the matrices
7248 
7249   Fortran Note:
7250   This does not free the array.
7251 
7252 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7253 @*/
7254 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7255 {
7256   Mat mat0;
7257 
7258   PetscFunctionBegin;
7259   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7260   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7261   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7262   PetscAssertPointer(mat, 2);
7263 
7264   mat0 = (*mat)[0];
7265   if (mat0 && mat0->ops->destroysubmatrices) {
7266     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7267   } else {
7268     PetscCall(MatDestroyMatrices(n, mat));
7269   }
7270   PetscFunctionReturn(PETSC_SUCCESS);
7271 }
7272 
7273 /*@C
7274   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7275 
7276   Collective
7277 
7278   Input Parameter:
7279 . mat - the matrix
7280 
7281   Output Parameter:
7282 . matstruct - the sequential matrix with the nonzero structure of mat
7283 
7284   Level: developer
7285 
7286 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7287 @*/
7288 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7289 {
7290   PetscFunctionBegin;
7291   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7292   PetscAssertPointer(matstruct, 2);
7293 
7294   PetscValidType(mat, 1);
7295   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7296   MatCheckPreallocated(mat, 1);
7297 
7298   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7299   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7300   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7301   PetscFunctionReturn(PETSC_SUCCESS);
7302 }
7303 
7304 /*@C
7305   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7306 
7307   Collective
7308 
7309   Input Parameter:
7310 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7311                        sequence of `MatGetSeqNonzeroStructure()`)
7312 
7313   Level: advanced
7314 
7315   Note:
7316   Frees not only the matrices, but also the array that contains the matrices
7317 
7318 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7319 @*/
7320 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7321 {
7322   PetscFunctionBegin;
7323   PetscAssertPointer(mat, 1);
7324   PetscCall(MatDestroy(mat));
7325   PetscFunctionReturn(PETSC_SUCCESS);
7326 }
7327 
7328 /*@
7329   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7330   replaces the index sets by larger ones that represent submatrices with
7331   additional overlap.
7332 
7333   Collective
7334 
7335   Input Parameters:
7336 + mat - the matrix
7337 . n   - the number of index sets
7338 . is  - the array of index sets (these index sets will changed during the call)
7339 - ov  - the additional overlap requested
7340 
7341   Options Database Key:
7342 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7343 
7344   Level: developer
7345 
7346   Note:
7347   The computed overlap preserves the matrix block sizes when the blocks are square.
7348   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7349   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7350 
7351 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7352 @*/
7353 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7354 {
7355   PetscInt i, bs, cbs;
7356 
7357   PetscFunctionBegin;
7358   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7359   PetscValidType(mat, 1);
7360   PetscValidLogicalCollectiveInt(mat, n, 2);
7361   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7362   if (n) {
7363     PetscAssertPointer(is, 3);
7364     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7365   }
7366   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7367   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7368   MatCheckPreallocated(mat, 1);
7369 
7370   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7371   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7372   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7373   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7374   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7375   if (bs == cbs) {
7376     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7377   }
7378   PetscFunctionReturn(PETSC_SUCCESS);
7379 }
7380 
7381 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7382 
7383 /*@
7384   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7385   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7386   additional overlap.
7387 
7388   Collective
7389 
7390   Input Parameters:
7391 + mat - the matrix
7392 . n   - the number of index sets
7393 . is  - the array of index sets (these index sets will changed during the call)
7394 - ov  - the additional overlap requested
7395 
7396   `   Options Database Key:
7397 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7398 
7399   Level: developer
7400 
7401 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7402 @*/
7403 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7404 {
7405   PetscInt i;
7406 
7407   PetscFunctionBegin;
7408   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7409   PetscValidType(mat, 1);
7410   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7411   if (n) {
7412     PetscAssertPointer(is, 3);
7413     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7414   }
7415   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7416   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7417   MatCheckPreallocated(mat, 1);
7418   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7419   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7420   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7421   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7422   PetscFunctionReturn(PETSC_SUCCESS);
7423 }
7424 
7425 /*@
7426   MatGetBlockSize - Returns the matrix block size.
7427 
7428   Not Collective
7429 
7430   Input Parameter:
7431 . mat - the matrix
7432 
7433   Output Parameter:
7434 . bs - block size
7435 
7436   Level: intermediate
7437 
7438   Notes:
7439   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7440 
7441   If the block size has not been set yet this routine returns 1.
7442 
7443 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7444 @*/
7445 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7446 {
7447   PetscFunctionBegin;
7448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7449   PetscAssertPointer(bs, 2);
7450   *bs = PetscAbs(mat->rmap->bs);
7451   PetscFunctionReturn(PETSC_SUCCESS);
7452 }
7453 
7454 /*@
7455   MatGetBlockSizes - Returns the matrix block row and column sizes.
7456 
7457   Not Collective
7458 
7459   Input Parameter:
7460 . mat - the matrix
7461 
7462   Output Parameters:
7463 + rbs - row block size
7464 - cbs - column block size
7465 
7466   Level: intermediate
7467 
7468   Notes:
7469   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7470   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7471 
7472   If a block size has not been set yet this routine returns 1.
7473 
7474 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7475 @*/
7476 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7477 {
7478   PetscFunctionBegin;
7479   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7480   if (rbs) PetscAssertPointer(rbs, 2);
7481   if (cbs) PetscAssertPointer(cbs, 3);
7482   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7483   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7484   PetscFunctionReturn(PETSC_SUCCESS);
7485 }
7486 
7487 /*@
7488   MatSetBlockSize - Sets the matrix block size.
7489 
7490   Logically Collective
7491 
7492   Input Parameters:
7493 + mat - the matrix
7494 - bs  - block size
7495 
7496   Level: intermediate
7497 
7498   Notes:
7499   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7500   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7501 
7502   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7503   is compatible with the matrix local sizes.
7504 
7505 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7506 @*/
7507 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7508 {
7509   PetscFunctionBegin;
7510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7511   PetscValidLogicalCollectiveInt(mat, bs, 2);
7512   PetscCall(MatSetBlockSizes(mat, bs, bs));
7513   PetscFunctionReturn(PETSC_SUCCESS);
7514 }
7515 
7516 typedef struct {
7517   PetscInt         n;
7518   IS              *is;
7519   Mat             *mat;
7520   PetscObjectState nonzerostate;
7521   Mat              C;
7522 } EnvelopeData;
7523 
7524 static PetscErrorCode EnvelopeDataDestroy(void *ptr)
7525 {
7526   EnvelopeData *edata = (EnvelopeData *)ptr;
7527 
7528   PetscFunctionBegin;
7529   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7530   PetscCall(PetscFree(edata->is));
7531   PetscCall(PetscFree(edata));
7532   PetscFunctionReturn(PETSC_SUCCESS);
7533 }
7534 
7535 /*@
7536   MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7537   the sizes of these blocks in the matrix. An individual block may lie over several processes.
7538 
7539   Collective
7540 
7541   Input Parameter:
7542 . mat - the matrix
7543 
7544   Level: intermediate
7545 
7546   Notes:
7547   There can be zeros within the blocks
7548 
7549   The blocks can overlap between processes, including laying on more than two processes
7550 
7551 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7552 @*/
7553 PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7554 {
7555   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7556   PetscInt          *diag, *odiag, sc;
7557   VecScatter         scatter;
7558   PetscScalar       *seqv;
7559   const PetscScalar *parv;
7560   const PetscInt    *ia, *ja;
7561   PetscBool          set, flag, done;
7562   Mat                AA = mat, A;
7563   MPI_Comm           comm;
7564   PetscMPIInt        rank, size, tag;
7565   MPI_Status         status;
7566   PetscContainer     container;
7567   EnvelopeData      *edata;
7568   Vec                seq, par;
7569   IS                 isglobal;
7570 
7571   PetscFunctionBegin;
7572   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7573   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7574   if (!set || !flag) {
7575     /* TODO: only needs nonzero structure of transpose */
7576     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7577     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7578   }
7579   PetscCall(MatAIJGetLocalMat(AA, &A));
7580   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7581   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7582 
7583   PetscCall(MatGetLocalSize(mat, &n, NULL));
7584   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7585   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7586   PetscCallMPI(MPI_Comm_size(comm, &size));
7587   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7588 
7589   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7590 
7591   if (rank > 0) {
7592     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7593     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7594   }
7595   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7596   for (i = 0; i < n; i++) {
7597     env = PetscMax(env, ja[ia[i + 1] - 1]);
7598     II  = rstart + i;
7599     if (env == II) {
7600       starts[lblocks]  = tbs;
7601       sizes[lblocks++] = 1 + II - tbs;
7602       tbs              = 1 + II;
7603     }
7604   }
7605   if (rank < size - 1) {
7606     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7607     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7608   }
7609 
7610   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7611   if (!set || !flag) PetscCall(MatDestroy(&AA));
7612   PetscCall(MatDestroy(&A));
7613 
7614   PetscCall(PetscNew(&edata));
7615   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7616   edata->n = lblocks;
7617   /* create IS needed for extracting blocks from the original matrix */
7618   PetscCall(PetscMalloc1(lblocks, &edata->is));
7619   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7620 
7621   /* Create the resulting inverse matrix structure with preallocation information */
7622   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7623   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7624   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7625   PetscCall(MatSetType(edata->C, MATAIJ));
7626 
7627   /* Communicate the start and end of each row, from each block to the correct rank */
7628   /* TODO: Use PetscSF instead of VecScatter */
7629   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7630   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7631   PetscCall(VecGetArrayWrite(seq, &seqv));
7632   for (PetscInt i = 0; i < lblocks; i++) {
7633     for (PetscInt j = 0; j < sizes[i]; j++) {
7634       seqv[cnt]     = starts[i];
7635       seqv[cnt + 1] = starts[i] + sizes[i];
7636       cnt += 2;
7637     }
7638   }
7639   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7640   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7641   sc -= cnt;
7642   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7643   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7644   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7645   PetscCall(ISDestroy(&isglobal));
7646   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7647   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7648   PetscCall(VecScatterDestroy(&scatter));
7649   PetscCall(VecDestroy(&seq));
7650   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7651   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7652   PetscCall(VecGetArrayRead(par, &parv));
7653   cnt = 0;
7654   PetscCall(MatGetSize(mat, NULL, &n));
7655   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7656     PetscInt start, end, d = 0, od = 0;
7657 
7658     start = (PetscInt)PetscRealPart(parv[cnt]);
7659     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7660     cnt += 2;
7661 
7662     if (start < cstart) {
7663       od += cstart - start + n - cend;
7664       d += cend - cstart;
7665     } else if (start < cend) {
7666       od += n - cend;
7667       d += cend - start;
7668     } else od += n - start;
7669     if (end <= cstart) {
7670       od -= cstart - end + n - cend;
7671       d -= cend - cstart;
7672     } else if (end < cend) {
7673       od -= n - cend;
7674       d -= cend - end;
7675     } else od -= n - end;
7676 
7677     odiag[i] = od;
7678     diag[i]  = d;
7679   }
7680   PetscCall(VecRestoreArrayRead(par, &parv));
7681   PetscCall(VecDestroy(&par));
7682   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7683   PetscCall(PetscFree2(diag, odiag));
7684   PetscCall(PetscFree2(sizes, starts));
7685 
7686   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7687   PetscCall(PetscContainerSetPointer(container, edata));
7688   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7689   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7690   PetscCall(PetscObjectDereference((PetscObject)container));
7691   PetscFunctionReturn(PETSC_SUCCESS);
7692 }
7693 
7694 /*@
7695   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7696 
7697   Collective
7698 
7699   Input Parameters:
7700 + A     - the matrix
7701 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7702 
7703   Output Parameter:
7704 . C - matrix with inverted block diagonal of `A`
7705 
7706   Level: advanced
7707 
7708   Note:
7709   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7710 
7711 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7712 @*/
7713 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7714 {
7715   PetscContainer   container;
7716   EnvelopeData    *edata;
7717   PetscObjectState nonzerostate;
7718 
7719   PetscFunctionBegin;
7720   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7721   if (!container) {
7722     PetscCall(MatComputeVariableBlockEnvelope(A));
7723     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7724   }
7725   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7726   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7727   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7728   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7729 
7730   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7731   *C = edata->C;
7732 
7733   for (PetscInt i = 0; i < edata->n; i++) {
7734     Mat          D;
7735     PetscScalar *dvalues;
7736 
7737     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7738     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7739     PetscCall(MatSeqDenseInvert(D));
7740     PetscCall(MatDenseGetArray(D, &dvalues));
7741     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7742     PetscCall(MatDestroy(&D));
7743   }
7744   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7745   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7746   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7747   PetscFunctionReturn(PETSC_SUCCESS);
7748 }
7749 
7750 /*@
7751   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7752 
7753   Logically Collective
7754 
7755   Input Parameters:
7756 + mat     - the matrix
7757 . nblocks - the number of blocks on this process, each block can only exist on a single process
7758 - bsizes  - the block sizes
7759 
7760   Level: intermediate
7761 
7762   Notes:
7763   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7764 
7765   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.
7766 
7767 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7768           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7769 @*/
7770 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7771 {
7772   PetscInt i, ncnt = 0, nlocal;
7773 
7774   PetscFunctionBegin;
7775   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7776   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7777   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);
7778   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7779   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);
7780   PetscCall(PetscFree(mat->bsizes));
7781   mat->nblocks = nblocks;
7782   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7783   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7784   PetscFunctionReturn(PETSC_SUCCESS);
7785 }
7786 
7787 /*@C
7788   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7789 
7790   Logically Collective; No Fortran Support
7791 
7792   Input Parameter:
7793 . mat - the matrix
7794 
7795   Output Parameters:
7796 + nblocks - the number of blocks on this process
7797 - bsizes  - the block sizes
7798 
7799   Level: intermediate
7800 
7801 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7802 @*/
7803 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7804 {
7805   PetscFunctionBegin;
7806   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7807   *nblocks = mat->nblocks;
7808   *bsizes  = mat->bsizes;
7809   PetscFunctionReturn(PETSC_SUCCESS);
7810 }
7811 
7812 /*@
7813   MatSetBlockSizes - Sets the matrix block row and column sizes.
7814 
7815   Logically Collective
7816 
7817   Input Parameters:
7818 + mat - the matrix
7819 . rbs - row block size
7820 - cbs - column block size
7821 
7822   Level: intermediate
7823 
7824   Notes:
7825   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7826   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7827   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7828 
7829   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7830   are compatible with the matrix local sizes.
7831 
7832   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7833 
7834 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7835 @*/
7836 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7837 {
7838   PetscFunctionBegin;
7839   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7840   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7841   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7842   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7843   if (mat->rmap->refcnt) {
7844     ISLocalToGlobalMapping l2g  = NULL;
7845     PetscLayout            nmap = NULL;
7846 
7847     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7848     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7849     PetscCall(PetscLayoutDestroy(&mat->rmap));
7850     mat->rmap          = nmap;
7851     mat->rmap->mapping = l2g;
7852   }
7853   if (mat->cmap->refcnt) {
7854     ISLocalToGlobalMapping l2g  = NULL;
7855     PetscLayout            nmap = NULL;
7856 
7857     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7858     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7859     PetscCall(PetscLayoutDestroy(&mat->cmap));
7860     mat->cmap          = nmap;
7861     mat->cmap->mapping = l2g;
7862   }
7863   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7864   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7865   PetscFunctionReturn(PETSC_SUCCESS);
7866 }
7867 
7868 /*@
7869   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7870 
7871   Logically Collective
7872 
7873   Input Parameters:
7874 + mat     - the matrix
7875 . fromRow - matrix from which to copy row block size
7876 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7877 
7878   Level: developer
7879 
7880 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7881 @*/
7882 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7883 {
7884   PetscFunctionBegin;
7885   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7886   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7887   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7888   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7889   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7890   PetscFunctionReturn(PETSC_SUCCESS);
7891 }
7892 
7893 /*@
7894   MatResidual - Default routine to calculate the residual r = b - Ax
7895 
7896   Collective
7897 
7898   Input Parameters:
7899 + mat - the matrix
7900 . b   - the right-hand-side
7901 - x   - the approximate solution
7902 
7903   Output Parameter:
7904 . r - location to store the residual
7905 
7906   Level: developer
7907 
7908 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7909 @*/
7910 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7911 {
7912   PetscFunctionBegin;
7913   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7914   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7915   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7916   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7917   PetscValidType(mat, 1);
7918   MatCheckPreallocated(mat, 1);
7919   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7920   if (!mat->ops->residual) {
7921     PetscCall(MatMult(mat, x, r));
7922     PetscCall(VecAYPX(r, -1.0, b));
7923   } else {
7924     PetscUseTypeMethod(mat, residual, b, x, r);
7925   }
7926   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7927   PetscFunctionReturn(PETSC_SUCCESS);
7928 }
7929 
7930 /*MC
7931     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7932 
7933     Synopsis:
7934     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7935 
7936     Not Collective
7937 
7938     Input Parameters:
7939 +   A - the matrix
7940 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7941 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7942 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7943                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7944                  always used.
7945 
7946     Output Parameters:
7947 +   n - number of local rows in the (possibly compressed) matrix
7948 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7949 .   ja - the column indices
7950 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7951            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7952 
7953     Level: developer
7954 
7955     Note:
7956     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7957 
7958 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7959 M*/
7960 
7961 /*MC
7962     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7963 
7964     Synopsis:
7965     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7966 
7967     Not Collective
7968 
7969     Input Parameters:
7970 +   A - the  matrix
7971 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7972 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7973     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7974                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7975                  always used.
7976 .   n - number of local rows in the (possibly compressed) matrix
7977 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7978 .   ja - the column indices
7979 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7980            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7981 
7982     Level: developer
7983 
7984 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7985 M*/
7986 
7987 /*@C
7988   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7989 
7990   Collective
7991 
7992   Input Parameters:
7993 + mat             - the matrix
7994 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7995 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7996 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7997                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7998                  always used.
7999 
8000   Output Parameters:
8001 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
8002 . 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
8003 . ja   - the column indices, use `NULL` if not needed
8004 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
8005            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
8006 
8007   Level: developer
8008 
8009   Notes:
8010   You CANNOT change any of the ia[] or ja[] values.
8011 
8012   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
8013 
8014   Fortran Notes:
8015   Use
8016 .vb
8017     PetscInt, pointer :: ia(:),ja(:)
8018     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
8019     ! Access the ith and jth entries via ia(i) and ja(j)
8020 .ve
8021 
8022   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
8023 
8024 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
8025 @*/
8026 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8027 {
8028   PetscFunctionBegin;
8029   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8030   PetscValidType(mat, 1);
8031   if (n) PetscAssertPointer(n, 5);
8032   if (ia) PetscAssertPointer(ia, 6);
8033   if (ja) PetscAssertPointer(ja, 7);
8034   if (done) PetscAssertPointer(done, 8);
8035   MatCheckPreallocated(mat, 1);
8036   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
8037   else {
8038     if (done) *done = PETSC_TRUE;
8039     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
8040     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8041     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
8042   }
8043   PetscFunctionReturn(PETSC_SUCCESS);
8044 }
8045 
8046 /*@C
8047   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
8048 
8049   Collective
8050 
8051   Input Parameters:
8052 + mat             - the matrix
8053 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8054 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
8055                 symmetrized
8056 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8057                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8058                  always used.
8059 . n               - number of columns in the (possibly compressed) matrix
8060 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
8061 - ja              - the row indices
8062 
8063   Output Parameter:
8064 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
8065 
8066   Level: developer
8067 
8068 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
8069 @*/
8070 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8071 {
8072   PetscFunctionBegin;
8073   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8074   PetscValidType(mat, 1);
8075   PetscAssertPointer(n, 5);
8076   if (ia) PetscAssertPointer(ia, 6);
8077   if (ja) PetscAssertPointer(ja, 7);
8078   PetscAssertPointer(done, 8);
8079   MatCheckPreallocated(mat, 1);
8080   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8081   else {
8082     *done = PETSC_TRUE;
8083     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8084   }
8085   PetscFunctionReturn(PETSC_SUCCESS);
8086 }
8087 
8088 /*@C
8089   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8090 
8091   Collective
8092 
8093   Input Parameters:
8094 + mat             - the matrix
8095 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8096 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8097 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8098                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8099                  always used.
8100 . n               - size of (possibly compressed) matrix
8101 . ia              - the row pointers
8102 - ja              - the column indices
8103 
8104   Output Parameter:
8105 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8106 
8107   Level: developer
8108 
8109   Note:
8110   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8111   us of the array after it has been restored. If you pass `NULL`, it will
8112   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8113 
8114   Fortran Note:
8115   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8116 
8117 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8118 @*/
8119 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8120 {
8121   PetscFunctionBegin;
8122   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8123   PetscValidType(mat, 1);
8124   if (ia) PetscAssertPointer(ia, 6);
8125   if (ja) PetscAssertPointer(ja, 7);
8126   if (done) PetscAssertPointer(done, 8);
8127   MatCheckPreallocated(mat, 1);
8128 
8129   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8130   else {
8131     if (done) *done = PETSC_TRUE;
8132     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8133     if (n) *n = 0;
8134     if (ia) *ia = NULL;
8135     if (ja) *ja = NULL;
8136   }
8137   PetscFunctionReturn(PETSC_SUCCESS);
8138 }
8139 
8140 /*@C
8141   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8142 
8143   Collective
8144 
8145   Input Parameters:
8146 + mat             - the matrix
8147 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8148 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8149 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8150                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8151                  always used.
8152 
8153   Output Parameters:
8154 + n    - size of (possibly compressed) matrix
8155 . ia   - the column pointers
8156 . ja   - the row indices
8157 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8158 
8159   Level: developer
8160 
8161 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8162 @*/
8163 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8164 {
8165   PetscFunctionBegin;
8166   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8167   PetscValidType(mat, 1);
8168   if (ia) PetscAssertPointer(ia, 6);
8169   if (ja) PetscAssertPointer(ja, 7);
8170   PetscAssertPointer(done, 8);
8171   MatCheckPreallocated(mat, 1);
8172 
8173   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8174   else {
8175     *done = PETSC_TRUE;
8176     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8177     if (n) *n = 0;
8178     if (ia) *ia = NULL;
8179     if (ja) *ja = NULL;
8180   }
8181   PetscFunctionReturn(PETSC_SUCCESS);
8182 }
8183 
8184 /*@C
8185   MatColoringPatch - Used inside matrix coloring routines that use `MatGetRowIJ()` and/or
8186   `MatGetColumnIJ()`.
8187 
8188   Collective
8189 
8190   Input Parameters:
8191 + mat        - the matrix
8192 . ncolors    - maximum color value
8193 . n          - number of entries in colorarray
8194 - colorarray - array indicating color for each column
8195 
8196   Output Parameter:
8197 . iscoloring - coloring generated using colorarray information
8198 
8199   Level: developer
8200 
8201 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8202 @*/
8203 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8204 {
8205   PetscFunctionBegin;
8206   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8207   PetscValidType(mat, 1);
8208   PetscAssertPointer(colorarray, 4);
8209   PetscAssertPointer(iscoloring, 5);
8210   MatCheckPreallocated(mat, 1);
8211 
8212   if (!mat->ops->coloringpatch) {
8213     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8214   } else {
8215     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8216   }
8217   PetscFunctionReturn(PETSC_SUCCESS);
8218 }
8219 
8220 /*@
8221   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8222 
8223   Logically Collective
8224 
8225   Input Parameter:
8226 . mat - the factored matrix to be reset
8227 
8228   Level: developer
8229 
8230   Notes:
8231   This routine should be used only with factored matrices formed by in-place
8232   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8233   format).  This option can save memory, for example, when solving nonlinear
8234   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8235   ILU(0) preconditioner.
8236 
8237   One can specify in-place ILU(0) factorization by calling
8238 .vb
8239      PCType(pc,PCILU);
8240      PCFactorSeUseInPlace(pc);
8241 .ve
8242   or by using the options -pc_type ilu -pc_factor_in_place
8243 
8244   In-place factorization ILU(0) can also be used as a local
8245   solver for the blocks within the block Jacobi or additive Schwarz
8246   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8247   for details on setting local solver options.
8248 
8249   Most users should employ the `KSP` interface for linear solvers
8250   instead of working directly with matrix algebra routines such as this.
8251   See, e.g., `KSPCreate()`.
8252 
8253 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8254 @*/
8255 PetscErrorCode MatSetUnfactored(Mat mat)
8256 {
8257   PetscFunctionBegin;
8258   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8259   PetscValidType(mat, 1);
8260   MatCheckPreallocated(mat, 1);
8261   mat->factortype = MAT_FACTOR_NONE;
8262   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8263   PetscUseTypeMethod(mat, setunfactored);
8264   PetscFunctionReturn(PETSC_SUCCESS);
8265 }
8266 
8267 /*MC
8268     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8269 
8270     Synopsis:
8271     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8272 
8273     Not Collective
8274 
8275     Input Parameter:
8276 .   x - matrix
8277 
8278     Output Parameters:
8279 +   xx_v - the Fortran pointer to the array
8280 -   ierr - error code
8281 
8282     Example of Usage:
8283 .vb
8284       PetscScalar, pointer xx_v(:,:)
8285       ....
8286       call MatDenseGetArrayF90(x,xx_v,ierr)
8287       a = xx_v(3)
8288       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8289 .ve
8290 
8291     Level: advanced
8292 
8293 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8294 M*/
8295 
8296 /*MC
8297     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8298     accessed with `MatDenseGetArrayF90()`.
8299 
8300     Synopsis:
8301     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8302 
8303     Not Collective
8304 
8305     Input Parameters:
8306 +   x - matrix
8307 -   xx_v - the Fortran90 pointer to the array
8308 
8309     Output Parameter:
8310 .   ierr - error code
8311 
8312     Example of Usage:
8313 .vb
8314        PetscScalar, pointer xx_v(:,:)
8315        ....
8316        call MatDenseGetArrayF90(x,xx_v,ierr)
8317        a = xx_v(3)
8318        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8319 .ve
8320 
8321     Level: advanced
8322 
8323 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8324 M*/
8325 
8326 /*MC
8327     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8328 
8329     Synopsis:
8330     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8331 
8332     Not Collective
8333 
8334     Input Parameter:
8335 .   x - matrix
8336 
8337     Output Parameters:
8338 +   xx_v - the Fortran pointer to the array
8339 -   ierr - error code
8340 
8341     Example of Usage:
8342 .vb
8343       PetscScalar, pointer xx_v(:)
8344       ....
8345       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8346       a = xx_v(3)
8347       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8348 .ve
8349 
8350     Level: advanced
8351 
8352 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8353 M*/
8354 
8355 /*MC
8356     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8357     accessed with `MatSeqAIJGetArrayF90()`.
8358 
8359     Synopsis:
8360     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8361 
8362     Not Collective
8363 
8364     Input Parameters:
8365 +   x - matrix
8366 -   xx_v - the Fortran90 pointer to the array
8367 
8368     Output Parameter:
8369 .   ierr - error code
8370 
8371     Example of Usage:
8372 .vb
8373        PetscScalar, pointer xx_v(:)
8374        ....
8375        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8376        a = xx_v(3)
8377        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8378 .ve
8379 
8380     Level: advanced
8381 
8382 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8383 M*/
8384 
8385 /*@
8386   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8387   as the original matrix.
8388 
8389   Collective
8390 
8391   Input Parameters:
8392 + mat   - the original matrix
8393 . isrow - parallel `IS` containing the rows this processor should obtain
8394 . 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.
8395 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8396 
8397   Output Parameter:
8398 . newmat - the new submatrix, of the same type as the original matrix
8399 
8400   Level: advanced
8401 
8402   Notes:
8403   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8404 
8405   Some matrix types place restrictions on the row and column indices, such
8406   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;
8407   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8408 
8409   The index sets may not have duplicate entries.
8410 
8411   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8412   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8413   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8414   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8415   you are finished using it.
8416 
8417   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8418   the input matrix.
8419 
8420   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8421 
8422   If `isrow` and `iscol` have a nontrivial block-size then the resulting matrix has this block-size as well. This feature
8423   is used by `PCFIELDSPLIT` to allow easy nesting of its use.
8424 
8425   Example usage:
8426   Consider the following 8x8 matrix with 34 non-zero values, that is
8427   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8428   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8429   as follows
8430 .vb
8431             1  2  0  |  0  3  0  |  0  4
8432     Proc0   0  5  6  |  7  0  0  |  8  0
8433             9  0 10  | 11  0  0  | 12  0
8434     -------------------------------------
8435            13  0 14  | 15 16 17  |  0  0
8436     Proc1   0 18  0  | 19 20 21  |  0  0
8437             0  0  0  | 22 23  0  | 24  0
8438     -------------------------------------
8439     Proc2  25 26 27  |  0  0 28  | 29  0
8440            30  0  0  | 31 32 33  |  0 34
8441 .ve
8442 
8443   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8444 
8445 .vb
8446             2  0  |  0  3  0  |  0
8447     Proc0   5  6  |  7  0  0  |  8
8448     -------------------------------
8449     Proc1  18  0  | 19 20 21  |  0
8450     -------------------------------
8451     Proc2  26 27  |  0  0 28  | 29
8452             0  0  | 31 32 33  |  0
8453 .ve
8454 
8455 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8456 @*/
8457 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8458 {
8459   PetscMPIInt size;
8460   Mat        *local;
8461   IS          iscoltmp;
8462   PetscBool   flg;
8463 
8464   PetscFunctionBegin;
8465   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8466   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8467   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8468   PetscAssertPointer(newmat, 5);
8469   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8470   PetscValidType(mat, 1);
8471   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8472   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8473 
8474   MatCheckPreallocated(mat, 1);
8475   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8476 
8477   if (!iscol || isrow == iscol) {
8478     PetscBool   stride;
8479     PetscMPIInt grabentirematrix = 0, grab;
8480     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8481     if (stride) {
8482       PetscInt first, step, n, rstart, rend;
8483       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8484       if (step == 1) {
8485         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8486         if (rstart == first) {
8487           PetscCall(ISGetLocalSize(isrow, &n));
8488           if (n == rend - rstart) grabentirematrix = 1;
8489         }
8490       }
8491     }
8492     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8493     if (grab) {
8494       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8495       if (cll == MAT_INITIAL_MATRIX) {
8496         *newmat = mat;
8497         PetscCall(PetscObjectReference((PetscObject)mat));
8498       }
8499       PetscFunctionReturn(PETSC_SUCCESS);
8500     }
8501   }
8502 
8503   if (!iscol) {
8504     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8505   } else {
8506     iscoltmp = iscol;
8507   }
8508 
8509   /* if original matrix is on just one processor then use submatrix generated */
8510   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8511     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8512     goto setproperties;
8513   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8514     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8515     *newmat = *local;
8516     PetscCall(PetscFree(local));
8517     goto setproperties;
8518   } else if (!mat->ops->createsubmatrix) {
8519     /* Create a new matrix type that implements the operation using the full matrix */
8520     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8521     switch (cll) {
8522     case MAT_INITIAL_MATRIX:
8523       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8524       break;
8525     case MAT_REUSE_MATRIX:
8526       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8527       break;
8528     default:
8529       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8530     }
8531     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8532     goto setproperties;
8533   }
8534 
8535   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8536   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8537   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8538 
8539 setproperties:
8540   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8541   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8542   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8543   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8544   PetscFunctionReturn(PETSC_SUCCESS);
8545 }
8546 
8547 /*@
8548   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8549 
8550   Not Collective
8551 
8552   Input Parameters:
8553 + A - the matrix we wish to propagate options from
8554 - B - the matrix we wish to propagate options to
8555 
8556   Level: beginner
8557 
8558   Note:
8559   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8560 
8561 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8562 @*/
8563 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8564 {
8565   PetscFunctionBegin;
8566   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8567   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8568   B->symmetry_eternal            = A->symmetry_eternal;
8569   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8570   B->symmetric                   = A->symmetric;
8571   B->structurally_symmetric      = A->structurally_symmetric;
8572   B->spd                         = A->spd;
8573   B->hermitian                   = A->hermitian;
8574   PetscFunctionReturn(PETSC_SUCCESS);
8575 }
8576 
8577 /*@
8578   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8579   used during the assembly process to store values that belong to
8580   other processors.
8581 
8582   Not Collective
8583 
8584   Input Parameters:
8585 + mat   - the matrix
8586 . size  - the initial size of the stash.
8587 - bsize - the initial size of the block-stash(if used).
8588 
8589   Options Database Keys:
8590 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8591 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8592 
8593   Level: intermediate
8594 
8595   Notes:
8596   The block-stash is used for values set with `MatSetValuesBlocked()` while
8597   the stash is used for values set with `MatSetValues()`
8598 
8599   Run with the option -info and look for output of the form
8600   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8601   to determine the appropriate value, MM, to use for size and
8602   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8603   to determine the value, BMM to use for bsize
8604 
8605 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8606 @*/
8607 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8608 {
8609   PetscFunctionBegin;
8610   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8611   PetscValidType(mat, 1);
8612   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8613   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8614   PetscFunctionReturn(PETSC_SUCCESS);
8615 }
8616 
8617 /*@
8618   MatInterpolateAdd - $w = y + A*x$ or $A^T*x$ depending on the shape of
8619   the matrix
8620 
8621   Neighbor-wise Collective
8622 
8623   Input Parameters:
8624 + A - the matrix
8625 . x - the vector to be multiplied by the interpolation operator
8626 - y - the vector to be added to the result
8627 
8628   Output Parameter:
8629 . w - the resulting vector
8630 
8631   Level: intermediate
8632 
8633   Notes:
8634   `w` may be the same vector as `y`.
8635 
8636   This allows one to use either the restriction or interpolation (its transpose)
8637   matrix to do the interpolation
8638 
8639 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8640 @*/
8641 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8642 {
8643   PetscInt M, N, Ny;
8644 
8645   PetscFunctionBegin;
8646   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8647   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8648   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8649   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8650   PetscCall(MatGetSize(A, &M, &N));
8651   PetscCall(VecGetSize(y, &Ny));
8652   if (M == Ny) {
8653     PetscCall(MatMultAdd(A, x, y, w));
8654   } else {
8655     PetscCall(MatMultTransposeAdd(A, x, y, w));
8656   }
8657   PetscFunctionReturn(PETSC_SUCCESS);
8658 }
8659 
8660 /*@
8661   MatInterpolate - $y = A*x$ or $A^T*x$ depending on the shape of
8662   the matrix
8663 
8664   Neighbor-wise Collective
8665 
8666   Input Parameters:
8667 + A - the matrix
8668 - x - the vector to be interpolated
8669 
8670   Output Parameter:
8671 . y - the resulting vector
8672 
8673   Level: intermediate
8674 
8675   Note:
8676   This allows one to use either the restriction or interpolation (its transpose)
8677   matrix to do the interpolation
8678 
8679 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8680 @*/
8681 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8682 {
8683   PetscInt M, N, Ny;
8684 
8685   PetscFunctionBegin;
8686   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8687   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8688   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8689   PetscCall(MatGetSize(A, &M, &N));
8690   PetscCall(VecGetSize(y, &Ny));
8691   if (M == Ny) {
8692     PetscCall(MatMult(A, x, y));
8693   } else {
8694     PetscCall(MatMultTranspose(A, x, y));
8695   }
8696   PetscFunctionReturn(PETSC_SUCCESS);
8697 }
8698 
8699 /*@
8700   MatRestrict - $y = A*x$ or $A^T*x$
8701 
8702   Neighbor-wise Collective
8703 
8704   Input Parameters:
8705 + A - the matrix
8706 - x - the vector to be restricted
8707 
8708   Output Parameter:
8709 . y - the resulting vector
8710 
8711   Level: intermediate
8712 
8713   Note:
8714   This allows one to use either the restriction or interpolation (its transpose)
8715   matrix to do the restriction
8716 
8717 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8718 @*/
8719 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8720 {
8721   PetscInt M, N, Nx;
8722 
8723   PetscFunctionBegin;
8724   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8725   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8726   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8727   PetscCall(MatGetSize(A, &M, &N));
8728   PetscCall(VecGetSize(x, &Nx));
8729   if (M == Nx) {
8730     PetscCall(MatMultTranspose(A, x, y));
8731   } else {
8732     PetscCall(MatMult(A, x, y));
8733   }
8734   PetscFunctionReturn(PETSC_SUCCESS);
8735 }
8736 
8737 /*@
8738   MatMatInterpolateAdd - $Y = W + A*X$ or $W + A^T*X$ depending on the shape of `A`
8739 
8740   Neighbor-wise Collective
8741 
8742   Input Parameters:
8743 + A - the matrix
8744 . x - the input dense matrix to be multiplied
8745 - w - the input dense matrix to be added to the result
8746 
8747   Output Parameter:
8748 . y - the output dense matrix
8749 
8750   Level: intermediate
8751 
8752   Note:
8753   This allows one to use either the restriction or interpolation (its transpose)
8754   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8755   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8756 
8757 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8758 @*/
8759 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8760 {
8761   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8762   PetscBool trans = PETSC_TRUE;
8763   MatReuse  reuse = MAT_INITIAL_MATRIX;
8764 
8765   PetscFunctionBegin;
8766   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8767   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8768   PetscValidType(x, 2);
8769   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8770   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8771   PetscCall(MatGetSize(A, &M, &N));
8772   PetscCall(MatGetSize(x, &Mx, &Nx));
8773   if (N == Mx) trans = PETSC_FALSE;
8774   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);
8775   Mo = trans ? N : M;
8776   if (*y) {
8777     PetscCall(MatGetSize(*y, &My, &Ny));
8778     if (Mo == My && Nx == Ny) {
8779       reuse = MAT_REUSE_MATRIX;
8780     } else {
8781       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);
8782       PetscCall(MatDestroy(y));
8783     }
8784   }
8785 
8786   if (w && *y == w) { /* this is to minimize changes in PCMG */
8787     PetscBool flg;
8788 
8789     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8790     if (w) {
8791       PetscInt My, Ny, Mw, Nw;
8792 
8793       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8794       PetscCall(MatGetSize(*y, &My, &Ny));
8795       PetscCall(MatGetSize(w, &Mw, &Nw));
8796       if (!flg || My != Mw || Ny != Nw) w = NULL;
8797     }
8798     if (!w) {
8799       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8800       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8801       PetscCall(PetscObjectDereference((PetscObject)w));
8802     } else {
8803       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8804     }
8805   }
8806   if (!trans) {
8807     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8808   } else {
8809     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8810   }
8811   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8812   PetscFunctionReturn(PETSC_SUCCESS);
8813 }
8814 
8815 /*@
8816   MatMatInterpolate - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8817 
8818   Neighbor-wise Collective
8819 
8820   Input Parameters:
8821 + A - the matrix
8822 - x - the input dense matrix
8823 
8824   Output Parameter:
8825 . y - the output dense matrix
8826 
8827   Level: intermediate
8828 
8829   Note:
8830   This allows one to use either the restriction or interpolation (its transpose)
8831   matrix to do the interpolation. `y` matrix can be reused if already created with the proper sizes,
8832   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8833 
8834 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8835 @*/
8836 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8837 {
8838   PetscFunctionBegin;
8839   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8840   PetscFunctionReturn(PETSC_SUCCESS);
8841 }
8842 
8843 /*@
8844   MatMatRestrict - $Y = A*X$ or $A^T*X$ depending on the shape of `A`
8845 
8846   Neighbor-wise Collective
8847 
8848   Input Parameters:
8849 + A - the matrix
8850 - x - the input dense matrix
8851 
8852   Output Parameter:
8853 . y - the output dense matrix
8854 
8855   Level: intermediate
8856 
8857   Note:
8858   This allows one to use either the restriction or interpolation (its transpose)
8859   matrix to do the restriction. `y` matrix can be reused if already created with the proper sizes,
8860   otherwise it will be recreated. `y` must be initialized to `NULL` if not supplied.
8861 
8862 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8863 @*/
8864 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8865 {
8866   PetscFunctionBegin;
8867   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8868   PetscFunctionReturn(PETSC_SUCCESS);
8869 }
8870 
8871 /*@
8872   MatGetNullSpace - retrieves the null space of a matrix.
8873 
8874   Logically Collective
8875 
8876   Input Parameters:
8877 + mat    - the matrix
8878 - nullsp - the null space object
8879 
8880   Level: developer
8881 
8882 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8883 @*/
8884 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8885 {
8886   PetscFunctionBegin;
8887   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8888   PetscAssertPointer(nullsp, 2);
8889   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8890   PetscFunctionReturn(PETSC_SUCCESS);
8891 }
8892 
8893 /*@
8894   MatSetNullSpace - attaches a null space to a matrix.
8895 
8896   Logically Collective
8897 
8898   Input Parameters:
8899 + mat    - the matrix
8900 - nullsp - the null space object
8901 
8902   Level: advanced
8903 
8904   Notes:
8905   This null space is used by the `KSP` linear solvers to solve singular systems.
8906 
8907   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`
8908 
8909   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
8910   to zero but the linear system will still be solved in a least squares sense.
8911 
8912   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8913   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)$.
8914   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
8915   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
8916   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$).
8917   This  \hat{b} can be obtained by calling `MatNullSpaceRemove()` with the null space of the transpose of the matrix.
8918 
8919   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8920   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8921   routine also automatically calls `MatSetTransposeNullSpace()`.
8922 
8923   The user should call `MatNullSpaceDestroy()`.
8924 
8925 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8926           `KSPSetPCSide()`
8927 @*/
8928 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8929 {
8930   PetscFunctionBegin;
8931   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8932   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8933   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8934   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8935   mat->nullsp = nullsp;
8936   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8937   PetscFunctionReturn(PETSC_SUCCESS);
8938 }
8939 
8940 /*@
8941   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8942 
8943   Logically Collective
8944 
8945   Input Parameters:
8946 + mat    - the matrix
8947 - nullsp - the null space object
8948 
8949   Level: developer
8950 
8951 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8952 @*/
8953 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8954 {
8955   PetscFunctionBegin;
8956   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8957   PetscValidType(mat, 1);
8958   PetscAssertPointer(nullsp, 2);
8959   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8960   PetscFunctionReturn(PETSC_SUCCESS);
8961 }
8962 
8963 /*@
8964   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8965 
8966   Logically Collective
8967 
8968   Input Parameters:
8969 + mat    - the matrix
8970 - nullsp - the null space object
8971 
8972   Level: advanced
8973 
8974   Notes:
8975   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8976 
8977   See `MatSetNullSpace()`
8978 
8979 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8980 @*/
8981 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8982 {
8983   PetscFunctionBegin;
8984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8985   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8986   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8987   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8988   mat->transnullsp = nullsp;
8989   PetscFunctionReturn(PETSC_SUCCESS);
8990 }
8991 
8992 /*@
8993   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8994   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8995 
8996   Logically Collective
8997 
8998   Input Parameters:
8999 + mat    - the matrix
9000 - nullsp - the null space object
9001 
9002   Level: advanced
9003 
9004   Notes:
9005   Overwrites any previous near null space that may have been attached
9006 
9007   You can remove the null space by calling this routine with an `nullsp` of `NULL`
9008 
9009 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
9010 @*/
9011 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
9012 {
9013   PetscFunctionBegin;
9014   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9015   PetscValidType(mat, 1);
9016   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
9017   MatCheckPreallocated(mat, 1);
9018   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
9019   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
9020   mat->nearnullsp = nullsp;
9021   PetscFunctionReturn(PETSC_SUCCESS);
9022 }
9023 
9024 /*@
9025   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
9026 
9027   Not Collective
9028 
9029   Input Parameter:
9030 . mat - the matrix
9031 
9032   Output Parameter:
9033 . nullsp - the null space object, `NULL` if not set
9034 
9035   Level: advanced
9036 
9037 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
9038 @*/
9039 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
9040 {
9041   PetscFunctionBegin;
9042   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9043   PetscValidType(mat, 1);
9044   PetscAssertPointer(nullsp, 2);
9045   MatCheckPreallocated(mat, 1);
9046   *nullsp = mat->nearnullsp;
9047   PetscFunctionReturn(PETSC_SUCCESS);
9048 }
9049 
9050 /*@C
9051   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
9052 
9053   Collective
9054 
9055   Input Parameters:
9056 + mat  - the matrix
9057 . row  - row/column permutation
9058 - info - information on desired factorization process
9059 
9060   Level: developer
9061 
9062   Notes:
9063   Probably really in-place only when level of fill is zero, otherwise allocates
9064   new space to store factored matrix and deletes previous memory.
9065 
9066   Most users should employ the `KSP` interface for linear solvers
9067   instead of working directly with matrix algebra routines such as this.
9068   See, e.g., `KSPCreate()`.
9069 
9070   Developer Note:
9071   The Fortran interface is not autogenerated as the
9072   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9073 
9074 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
9075 @*/
9076 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
9077 {
9078   PetscFunctionBegin;
9079   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9080   PetscValidType(mat, 1);
9081   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
9082   PetscAssertPointer(info, 3);
9083   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
9084   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9085   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9086   MatCheckPreallocated(mat, 1);
9087   PetscUseTypeMethod(mat, iccfactor, row, info);
9088   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9089   PetscFunctionReturn(PETSC_SUCCESS);
9090 }
9091 
9092 /*@
9093   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9094   ghosted ones.
9095 
9096   Not Collective
9097 
9098   Input Parameters:
9099 + mat  - the matrix
9100 - diag - the diagonal values, including ghost ones
9101 
9102   Level: developer
9103 
9104   Notes:
9105   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9106 
9107   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9108 
9109 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9110 @*/
9111 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9112 {
9113   PetscMPIInt size;
9114 
9115   PetscFunctionBegin;
9116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9117   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9118   PetscValidType(mat, 1);
9119 
9120   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9121   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9122   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9123   if (size == 1) {
9124     PetscInt n, m;
9125     PetscCall(VecGetSize(diag, &n));
9126     PetscCall(MatGetSize(mat, NULL, &m));
9127     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9128     PetscCall(MatDiagonalScale(mat, NULL, diag));
9129   } else {
9130     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9131   }
9132   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9133   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9134   PetscFunctionReturn(PETSC_SUCCESS);
9135 }
9136 
9137 /*@
9138   MatGetInertia - Gets the inertia from a factored matrix
9139 
9140   Collective
9141 
9142   Input Parameter:
9143 . mat - the matrix
9144 
9145   Output Parameters:
9146 + nneg  - number of negative eigenvalues
9147 . nzero - number of zero eigenvalues
9148 - npos  - number of positive eigenvalues
9149 
9150   Level: advanced
9151 
9152   Note:
9153   Matrix must have been factored by `MatCholeskyFactor()`
9154 
9155 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9156 @*/
9157 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9158 {
9159   PetscFunctionBegin;
9160   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9161   PetscValidType(mat, 1);
9162   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9163   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9164   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9165   PetscFunctionReturn(PETSC_SUCCESS);
9166 }
9167 
9168 /*@C
9169   MatSolves - Solves $A x = b$, given a factored matrix, for a collection of vectors
9170 
9171   Neighbor-wise Collective
9172 
9173   Input Parameters:
9174 + mat - the factored matrix obtained with `MatGetFactor()`
9175 - b   - the right-hand-side vectors
9176 
9177   Output Parameter:
9178 . x - the result vectors
9179 
9180   Level: developer
9181 
9182   Note:
9183   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9184   call `MatSolves`(A,x,x).
9185 
9186 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9187 @*/
9188 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9189 {
9190   PetscFunctionBegin;
9191   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9192   PetscValidType(mat, 1);
9193   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9194   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9195   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9196 
9197   MatCheckPreallocated(mat, 1);
9198   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9199   PetscUseTypeMethod(mat, solves, b, x);
9200   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9201   PetscFunctionReturn(PETSC_SUCCESS);
9202 }
9203 
9204 /*@
9205   MatIsSymmetric - Test whether a matrix is symmetric
9206 
9207   Collective
9208 
9209   Input Parameters:
9210 + A   - the matrix to test
9211 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9212 
9213   Output Parameter:
9214 . flg - the result
9215 
9216   Level: intermediate
9217 
9218   Notes:
9219   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9220 
9221   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9222 
9223   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9224   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9225 
9226 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9227           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9228 @*/
9229 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9230 {
9231   PetscFunctionBegin;
9232   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9233   PetscAssertPointer(flg, 3);
9234 
9235   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9236   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9237   else {
9238     PetscUseTypeMethod(A, issymmetric, tol, flg);
9239     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9240   }
9241   PetscFunctionReturn(PETSC_SUCCESS);
9242 }
9243 
9244 /*@
9245   MatIsHermitian - Test whether a matrix is Hermitian
9246 
9247   Collective
9248 
9249   Input Parameters:
9250 + A   - the matrix to test
9251 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9252 
9253   Output Parameter:
9254 . flg - the result
9255 
9256   Level: intermediate
9257 
9258   Notes:
9259   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9260 
9261   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9262 
9263   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9264   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9265 
9266 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9267           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9268 @*/
9269 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9270 {
9271   PetscFunctionBegin;
9272   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9273   PetscAssertPointer(flg, 3);
9274 
9275   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9276   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9277   else {
9278     PetscUseTypeMethod(A, ishermitian, tol, flg);
9279     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9280   }
9281   PetscFunctionReturn(PETSC_SUCCESS);
9282 }
9283 
9284 /*@
9285   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9286 
9287   Not Collective
9288 
9289   Input Parameter:
9290 . A - the matrix to check
9291 
9292   Output Parameters:
9293 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9294 - flg - the result (only valid if set is `PETSC_TRUE`)
9295 
9296   Level: advanced
9297 
9298   Notes:
9299   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9300   if you want it explicitly checked
9301 
9302   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9303   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9304 
9305 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9306 @*/
9307 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9308 {
9309   PetscFunctionBegin;
9310   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9311   PetscAssertPointer(set, 2);
9312   PetscAssertPointer(flg, 3);
9313   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9314     *set = PETSC_TRUE;
9315     *flg = PetscBool3ToBool(A->symmetric);
9316   } else {
9317     *set = PETSC_FALSE;
9318   }
9319   PetscFunctionReturn(PETSC_SUCCESS);
9320 }
9321 
9322 /*@
9323   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9324 
9325   Not Collective
9326 
9327   Input Parameter:
9328 . A - the matrix to check
9329 
9330   Output Parameters:
9331 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9332 - flg - the result (only valid if set is `PETSC_TRUE`)
9333 
9334   Level: advanced
9335 
9336   Notes:
9337   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9338 
9339   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9340   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9341 
9342 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9343 @*/
9344 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9345 {
9346   PetscFunctionBegin;
9347   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9348   PetscAssertPointer(set, 2);
9349   PetscAssertPointer(flg, 3);
9350   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9351     *set = PETSC_TRUE;
9352     *flg = PetscBool3ToBool(A->spd);
9353   } else {
9354     *set = PETSC_FALSE;
9355   }
9356   PetscFunctionReturn(PETSC_SUCCESS);
9357 }
9358 
9359 /*@
9360   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9361 
9362   Not Collective
9363 
9364   Input Parameter:
9365 . A - the matrix to check
9366 
9367   Output Parameters:
9368 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9369 - flg - the result (only valid if set is `PETSC_TRUE`)
9370 
9371   Level: advanced
9372 
9373   Notes:
9374   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9375   if you want it explicitly checked
9376 
9377   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9378   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9379 
9380 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9381 @*/
9382 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9383 {
9384   PetscFunctionBegin;
9385   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9386   PetscAssertPointer(set, 2);
9387   PetscAssertPointer(flg, 3);
9388   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9389     *set = PETSC_TRUE;
9390     *flg = PetscBool3ToBool(A->hermitian);
9391   } else {
9392     *set = PETSC_FALSE;
9393   }
9394   PetscFunctionReturn(PETSC_SUCCESS);
9395 }
9396 
9397 /*@
9398   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9399 
9400   Collective
9401 
9402   Input Parameter:
9403 . A - the matrix to test
9404 
9405   Output Parameter:
9406 . flg - the result
9407 
9408   Level: intermediate
9409 
9410   Notes:
9411   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9412 
9413   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
9414   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9415 
9416 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9417 @*/
9418 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9419 {
9420   PetscFunctionBegin;
9421   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9422   PetscAssertPointer(flg, 2);
9423   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9424     *flg = PetscBool3ToBool(A->structurally_symmetric);
9425   } else {
9426     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9427     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9428   }
9429   PetscFunctionReturn(PETSC_SUCCESS);
9430 }
9431 
9432 /*@
9433   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9434 
9435   Not Collective
9436 
9437   Input Parameter:
9438 . A - the matrix to check
9439 
9440   Output Parameters:
9441 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9442 - flg - the result (only valid if set is PETSC_TRUE)
9443 
9444   Level: advanced
9445 
9446   Notes:
9447   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
9448   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9449 
9450   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9451 
9452 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9453 @*/
9454 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9455 {
9456   PetscFunctionBegin;
9457   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9458   PetscAssertPointer(set, 2);
9459   PetscAssertPointer(flg, 3);
9460   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9461     *set = PETSC_TRUE;
9462     *flg = PetscBool3ToBool(A->structurally_symmetric);
9463   } else {
9464     *set = PETSC_FALSE;
9465   }
9466   PetscFunctionReturn(PETSC_SUCCESS);
9467 }
9468 
9469 /*@
9470   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9471   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9472 
9473   Not Collective
9474 
9475   Input Parameter:
9476 . mat - the matrix
9477 
9478   Output Parameters:
9479 + nstash    - the size of the stash
9480 . reallocs  - the number of additional mallocs incurred.
9481 . bnstash   - the size of the block stash
9482 - breallocs - the number of additional mallocs incurred.in the block stash
9483 
9484   Level: advanced
9485 
9486 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9487 @*/
9488 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9489 {
9490   PetscFunctionBegin;
9491   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9492   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9493   PetscFunctionReturn(PETSC_SUCCESS);
9494 }
9495 
9496 /*@C
9497   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9498   parallel layout, `PetscLayout` for rows and columns
9499 
9500   Collective
9501 
9502   Input Parameter:
9503 . mat - the matrix
9504 
9505   Output Parameters:
9506 + right - (optional) vector that the matrix can be multiplied against
9507 - left  - (optional) vector that the matrix vector product can be stored in
9508 
9509   Level: advanced
9510 
9511   Notes:
9512   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()`.
9513 
9514   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9515 
9516 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9517 @*/
9518 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9519 {
9520   PetscFunctionBegin;
9521   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9522   PetscValidType(mat, 1);
9523   if (mat->ops->getvecs) {
9524     PetscUseTypeMethod(mat, getvecs, right, left);
9525   } else {
9526     if (right) {
9527       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9528       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9529       PetscCall(VecSetType(*right, mat->defaultvectype));
9530 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9531       if (mat->boundtocpu && mat->bindingpropagates) {
9532         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9533         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9534       }
9535 #endif
9536     }
9537     if (left) {
9538       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9539       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9540       PetscCall(VecSetType(*left, mat->defaultvectype));
9541 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9542       if (mat->boundtocpu && mat->bindingpropagates) {
9543         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9544         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9545       }
9546 #endif
9547     }
9548   }
9549   PetscFunctionReturn(PETSC_SUCCESS);
9550 }
9551 
9552 /*@C
9553   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9554   with default values.
9555 
9556   Not Collective
9557 
9558   Input Parameter:
9559 . info - the `MatFactorInfo` data structure
9560 
9561   Level: developer
9562 
9563   Notes:
9564   The solvers are generally used through the `KSP` and `PC` objects, for example
9565   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9566 
9567   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9568 
9569   Developer Note:
9570   The Fortran interface is not autogenerated as the
9571   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9572 
9573 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9574 @*/
9575 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9576 {
9577   PetscFunctionBegin;
9578   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9579   PetscFunctionReturn(PETSC_SUCCESS);
9580 }
9581 
9582 /*@
9583   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9584 
9585   Collective
9586 
9587   Input Parameters:
9588 + mat - the factored matrix
9589 - is  - the index set defining the Schur indices (0-based)
9590 
9591   Level: advanced
9592 
9593   Notes:
9594   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9595 
9596   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9597 
9598   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9599 
9600 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9601           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9602 @*/
9603 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9604 {
9605   PetscErrorCode (*f)(Mat, IS);
9606 
9607   PetscFunctionBegin;
9608   PetscValidType(mat, 1);
9609   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9610   PetscValidType(is, 2);
9611   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9612   PetscCheckSameComm(mat, 1, is, 2);
9613   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9614   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9615   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9616   PetscCall(MatDestroy(&mat->schur));
9617   PetscCall((*f)(mat, is));
9618   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9619   PetscFunctionReturn(PETSC_SUCCESS);
9620 }
9621 
9622 /*@
9623   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9624 
9625   Logically Collective
9626 
9627   Input Parameters:
9628 + F      - the factored matrix obtained by calling `MatGetFactor()`
9629 . S      - location where to return the Schur complement, can be `NULL`
9630 - status - the status of the Schur complement matrix, can be `NULL`
9631 
9632   Level: advanced
9633 
9634   Notes:
9635   You must call `MatFactorSetSchurIS()` before calling this routine.
9636 
9637   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9638 
9639   The routine provides a copy of the Schur matrix stored within the solver data structures.
9640   The caller must destroy the object when it is no longer needed.
9641   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9642 
9643   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)
9644 
9645   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9646 
9647   Developer Note:
9648   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9649   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9650 
9651 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9652 @*/
9653 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9654 {
9655   PetscFunctionBegin;
9656   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9657   if (S) PetscAssertPointer(S, 2);
9658   if (status) PetscAssertPointer(status, 3);
9659   if (S) {
9660     PetscErrorCode (*f)(Mat, Mat *);
9661 
9662     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9663     if (f) {
9664       PetscCall((*f)(F, S));
9665     } else {
9666       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9667     }
9668   }
9669   if (status) *status = F->schur_status;
9670   PetscFunctionReturn(PETSC_SUCCESS);
9671 }
9672 
9673 /*@
9674   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9675 
9676   Logically Collective
9677 
9678   Input Parameters:
9679 + F      - the factored matrix obtained by calling `MatGetFactor()`
9680 . S      - location where to return the Schur complement, can be `NULL`
9681 - status - the status of the Schur complement matrix, can be `NULL`
9682 
9683   Level: advanced
9684 
9685   Notes:
9686   You must call `MatFactorSetSchurIS()` before calling this routine.
9687 
9688   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9689 
9690   The routine returns a the Schur Complement stored within the data structures of the solver.
9691 
9692   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9693 
9694   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9695 
9696   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9697 
9698   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9699 
9700 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9701 @*/
9702 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9703 {
9704   PetscFunctionBegin;
9705   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9706   if (S) {
9707     PetscAssertPointer(S, 2);
9708     *S = F->schur;
9709   }
9710   if (status) {
9711     PetscAssertPointer(status, 3);
9712     *status = F->schur_status;
9713   }
9714   PetscFunctionReturn(PETSC_SUCCESS);
9715 }
9716 
9717 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9718 {
9719   Mat S = F->schur;
9720 
9721   PetscFunctionBegin;
9722   switch (F->schur_status) {
9723   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9724   case MAT_FACTOR_SCHUR_INVERTED:
9725     if (S) {
9726       S->ops->solve             = NULL;
9727       S->ops->matsolve          = NULL;
9728       S->ops->solvetranspose    = NULL;
9729       S->ops->matsolvetranspose = NULL;
9730       S->ops->solveadd          = NULL;
9731       S->ops->solvetransposeadd = NULL;
9732       S->factortype             = MAT_FACTOR_NONE;
9733       PetscCall(PetscFree(S->solvertype));
9734     }
9735   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9736     break;
9737   default:
9738     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9739   }
9740   PetscFunctionReturn(PETSC_SUCCESS);
9741 }
9742 
9743 /*@
9744   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9745 
9746   Logically Collective
9747 
9748   Input Parameters:
9749 + F      - the factored matrix obtained by calling `MatGetFactor()`
9750 . S      - location where the Schur complement is stored
9751 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9752 
9753   Level: advanced
9754 
9755 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9756 @*/
9757 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9758 {
9759   PetscFunctionBegin;
9760   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9761   if (S) {
9762     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9763     *S = NULL;
9764   }
9765   F->schur_status = status;
9766   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9767   PetscFunctionReturn(PETSC_SUCCESS);
9768 }
9769 
9770 /*@
9771   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9772 
9773   Logically Collective
9774 
9775   Input Parameters:
9776 + F   - the factored matrix obtained by calling `MatGetFactor()`
9777 . rhs - location where the right hand side of the Schur complement system is stored
9778 - sol - location where the solution of the Schur complement system has to be returned
9779 
9780   Level: advanced
9781 
9782   Notes:
9783   The sizes of the vectors should match the size of the Schur complement
9784 
9785   Must be called after `MatFactorSetSchurIS()`
9786 
9787 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9788 @*/
9789 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9790 {
9791   PetscFunctionBegin;
9792   PetscValidType(F, 1);
9793   PetscValidType(rhs, 2);
9794   PetscValidType(sol, 3);
9795   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9796   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9797   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9798   PetscCheckSameComm(F, 1, rhs, 2);
9799   PetscCheckSameComm(F, 1, sol, 3);
9800   PetscCall(MatFactorFactorizeSchurComplement(F));
9801   switch (F->schur_status) {
9802   case MAT_FACTOR_SCHUR_FACTORED:
9803     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9804     break;
9805   case MAT_FACTOR_SCHUR_INVERTED:
9806     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9807     break;
9808   default:
9809     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9810   }
9811   PetscFunctionReturn(PETSC_SUCCESS);
9812 }
9813 
9814 /*@
9815   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9816 
9817   Logically Collective
9818 
9819   Input Parameters:
9820 + F   - the factored matrix obtained by calling `MatGetFactor()`
9821 . rhs - location where the right hand side of the Schur complement system is stored
9822 - sol - location where the solution of the Schur complement system has to be returned
9823 
9824   Level: advanced
9825 
9826   Notes:
9827   The sizes of the vectors should match the size of the Schur complement
9828 
9829   Must be called after `MatFactorSetSchurIS()`
9830 
9831 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9832 @*/
9833 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9834 {
9835   PetscFunctionBegin;
9836   PetscValidType(F, 1);
9837   PetscValidType(rhs, 2);
9838   PetscValidType(sol, 3);
9839   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9840   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9841   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9842   PetscCheckSameComm(F, 1, rhs, 2);
9843   PetscCheckSameComm(F, 1, sol, 3);
9844   PetscCall(MatFactorFactorizeSchurComplement(F));
9845   switch (F->schur_status) {
9846   case MAT_FACTOR_SCHUR_FACTORED:
9847     PetscCall(MatSolve(F->schur, rhs, sol));
9848     break;
9849   case MAT_FACTOR_SCHUR_INVERTED:
9850     PetscCall(MatMult(F->schur, rhs, sol));
9851     break;
9852   default:
9853     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9854   }
9855   PetscFunctionReturn(PETSC_SUCCESS);
9856 }
9857 
9858 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9859 #if PetscDefined(HAVE_CUDA)
9860 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9861 #endif
9862 
9863 /* Schur status updated in the interface */
9864 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9865 {
9866   Mat S = F->schur;
9867 
9868   PetscFunctionBegin;
9869   if (S) {
9870     PetscMPIInt size;
9871     PetscBool   isdense, isdensecuda;
9872 
9873     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9874     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9875     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9876     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9877     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9878     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9879     if (isdense) {
9880       PetscCall(MatSeqDenseInvertFactors_Private(S));
9881     } else if (isdensecuda) {
9882 #if defined(PETSC_HAVE_CUDA)
9883       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9884 #endif
9885     }
9886     // HIP??????????????
9887     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9888   }
9889   PetscFunctionReturn(PETSC_SUCCESS);
9890 }
9891 
9892 /*@
9893   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9894 
9895   Logically Collective
9896 
9897   Input Parameter:
9898 . F - the factored matrix obtained by calling `MatGetFactor()`
9899 
9900   Level: advanced
9901 
9902   Notes:
9903   Must be called after `MatFactorSetSchurIS()`.
9904 
9905   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9906 
9907 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9908 @*/
9909 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9910 {
9911   PetscFunctionBegin;
9912   PetscValidType(F, 1);
9913   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9914   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9915   PetscCall(MatFactorFactorizeSchurComplement(F));
9916   PetscCall(MatFactorInvertSchurComplement_Private(F));
9917   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9918   PetscFunctionReturn(PETSC_SUCCESS);
9919 }
9920 
9921 /*@
9922   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9923 
9924   Logically Collective
9925 
9926   Input Parameter:
9927 . F - the factored matrix obtained by calling `MatGetFactor()`
9928 
9929   Level: advanced
9930 
9931   Note:
9932   Must be called after `MatFactorSetSchurIS()`
9933 
9934 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9935 @*/
9936 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9937 {
9938   MatFactorInfo info;
9939 
9940   PetscFunctionBegin;
9941   PetscValidType(F, 1);
9942   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9943   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9944   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9945   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9946   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9947     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9948   } else {
9949     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9950   }
9951   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9952   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9953   PetscFunctionReturn(PETSC_SUCCESS);
9954 }
9955 
9956 /*@
9957   MatPtAP - Creates the matrix product $C = P^T * A * P$
9958 
9959   Neighbor-wise Collective
9960 
9961   Input Parameters:
9962 + A     - the matrix
9963 . P     - the projection matrix
9964 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9965 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9966           if the result is a dense matrix this is irrelevant
9967 
9968   Output Parameter:
9969 . C - the product matrix
9970 
9971   Level: intermediate
9972 
9973   Notes:
9974   C will be created and must be destroyed by the user with `MatDestroy()`.
9975 
9976   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9977 
9978   Developer Note:
9979   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9980 
9981 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9982 @*/
9983 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9984 {
9985   PetscFunctionBegin;
9986   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9987   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9988 
9989   if (scall == MAT_INITIAL_MATRIX) {
9990     PetscCall(MatProductCreate(A, P, NULL, C));
9991     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9992     PetscCall(MatProductSetAlgorithm(*C, "default"));
9993     PetscCall(MatProductSetFill(*C, fill));
9994 
9995     (*C)->product->api_user = PETSC_TRUE;
9996     PetscCall(MatProductSetFromOptions(*C));
9997     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);
9998     PetscCall(MatProductSymbolic(*C));
9999   } else { /* scall == MAT_REUSE_MATRIX */
10000     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
10001   }
10002 
10003   PetscCall(MatProductNumeric(*C));
10004   (*C)->symmetric = A->symmetric;
10005   (*C)->spd       = A->spd;
10006   PetscFunctionReturn(PETSC_SUCCESS);
10007 }
10008 
10009 /*@
10010   MatRARt - Creates the matrix product $C = R * A * R^T$
10011 
10012   Neighbor-wise Collective
10013 
10014   Input Parameters:
10015 + A     - the matrix
10016 . R     - the projection matrix
10017 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10018 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
10019           if the result is a dense matrix this is irrelevant
10020 
10021   Output Parameter:
10022 . C - the product matrix
10023 
10024   Level: intermediate
10025 
10026   Notes:
10027   C will be created and must be destroyed by the user with `MatDestroy()`.
10028 
10029   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
10030 
10031   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
10032   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
10033   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
10034   We recommend using MatPtAP().
10035 
10036 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
10037 @*/
10038 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
10039 {
10040   PetscFunctionBegin;
10041   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
10042   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10043 
10044   if (scall == MAT_INITIAL_MATRIX) {
10045     PetscCall(MatProductCreate(A, R, NULL, C));
10046     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
10047     PetscCall(MatProductSetAlgorithm(*C, "default"));
10048     PetscCall(MatProductSetFill(*C, fill));
10049 
10050     (*C)->product->api_user = PETSC_TRUE;
10051     PetscCall(MatProductSetFromOptions(*C));
10052     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);
10053     PetscCall(MatProductSymbolic(*C));
10054   } else { /* scall == MAT_REUSE_MATRIX */
10055     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
10056   }
10057 
10058   PetscCall(MatProductNumeric(*C));
10059   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10060   PetscFunctionReturn(PETSC_SUCCESS);
10061 }
10062 
10063 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
10064 {
10065   PetscFunctionBegin;
10066   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10067 
10068   if (scall == MAT_INITIAL_MATRIX) {
10069     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
10070     PetscCall(MatProductCreate(A, B, NULL, C));
10071     PetscCall(MatProductSetType(*C, ptype));
10072     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
10073     PetscCall(MatProductSetFill(*C, fill));
10074 
10075     (*C)->product->api_user = PETSC_TRUE;
10076     PetscCall(MatProductSetFromOptions(*C));
10077     PetscCall(MatProductSymbolic(*C));
10078   } else { /* scall == MAT_REUSE_MATRIX */
10079     Mat_Product *product = (*C)->product;
10080     PetscBool    isdense;
10081 
10082     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
10083     if (isdense && product && product->type != ptype) {
10084       PetscCall(MatProductClear(*C));
10085       product = NULL;
10086     }
10087     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
10088     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10089       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10090       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10091       product           = (*C)->product;
10092       product->fill     = fill;
10093       product->api_user = PETSC_TRUE;
10094       product->clear    = PETSC_TRUE;
10095 
10096       PetscCall(MatProductSetType(*C, ptype));
10097       PetscCall(MatProductSetFromOptions(*C));
10098       PetscCheck((*C)->ops->productsymbolic, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "MatProduct %s not supported for %s and %s", MatProductTypes[ptype], ((PetscObject)A)->type_name, ((PetscObject)B)->type_name);
10099       PetscCall(MatProductSymbolic(*C));
10100     } else { /* user may change input matrices A or B when REUSE */
10101       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10102     }
10103   }
10104   PetscCall(MatProductNumeric(*C));
10105   PetscFunctionReturn(PETSC_SUCCESS);
10106 }
10107 
10108 /*@
10109   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10110 
10111   Neighbor-wise Collective
10112 
10113   Input Parameters:
10114 + A     - the left matrix
10115 . B     - the right matrix
10116 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10117 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10118           if the result is a dense matrix this is irrelevant
10119 
10120   Output Parameter:
10121 . C - the product matrix
10122 
10123   Notes:
10124   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10125 
10126   `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
10127   call to this function with `MAT_INITIAL_MATRIX`.
10128 
10129   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10130 
10131   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`,
10132   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10133 
10134   Example of Usage:
10135 .vb
10136      MatProductCreate(A,B,NULL,&C);
10137      MatProductSetType(C,MATPRODUCT_AB);
10138      MatProductSymbolic(C);
10139      MatProductNumeric(C); // compute C=A * B
10140      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10141      MatProductNumeric(C);
10142      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10143      MatProductNumeric(C);
10144 .ve
10145 
10146   Level: intermediate
10147 
10148 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10149 @*/
10150 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10151 {
10152   PetscFunctionBegin;
10153   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10154   PetscFunctionReturn(PETSC_SUCCESS);
10155 }
10156 
10157 /*@
10158   MatMatTransposeMult - Performs matrix-matrix multiplication $C = A*B^T$.
10159 
10160   Neighbor-wise Collective
10161 
10162   Input Parameters:
10163 + A     - the left matrix
10164 . B     - the right matrix
10165 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10166 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10167 
10168   Output Parameter:
10169 . C - the product matrix
10170 
10171   Options Database Key:
10172 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10173               first redundantly copies the transposed `B` matrix on each process and requires O(log P) communication complexity;
10174               the second never stores more than one portion of the `B` matrix at a time but requires O(P) communication complexity.
10175 
10176   Level: intermediate
10177 
10178   Notes:
10179   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10180 
10181   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10182 
10183   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10184   actually needed.
10185 
10186   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10187   and for pairs of `MATMPIDENSE` matrices.
10188 
10189   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10190 
10191 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10192 @*/
10193 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10194 {
10195   PetscFunctionBegin;
10196   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10197   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10198   PetscFunctionReturn(PETSC_SUCCESS);
10199 }
10200 
10201 /*@
10202   MatTransposeMatMult - Performs matrix-matrix multiplication $C = A^T*B$.
10203 
10204   Neighbor-wise Collective
10205 
10206   Input Parameters:
10207 + A     - the left matrix
10208 . B     - the right matrix
10209 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10210 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10211 
10212   Output Parameter:
10213 . C - the product matrix
10214 
10215   Level: intermediate
10216 
10217   Notes:
10218   `C` will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10219 
10220   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10221 
10222   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10223 
10224   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10225   actually needed.
10226 
10227   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10228   which inherit from `MATSEQAIJ`.  `C` will be of the same type as the input matrices.
10229 
10230 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10231 @*/
10232 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10233 {
10234   PetscFunctionBegin;
10235   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10236   PetscFunctionReturn(PETSC_SUCCESS);
10237 }
10238 
10239 /*@
10240   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10241 
10242   Neighbor-wise Collective
10243 
10244   Input Parameters:
10245 + A     - the left matrix
10246 . B     - the middle matrix
10247 . C     - the right matrix
10248 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10249 - 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
10250           if the result is a dense matrix this is irrelevant
10251 
10252   Output Parameter:
10253 . D - the product matrix
10254 
10255   Level: intermediate
10256 
10257   Notes:
10258   Unless `scall` is `MAT_REUSE_MATRIX` D will be created.
10259 
10260   `MAT_REUSE_MATRIX` can only be used if the matrices `A`, `B`, and `C` have the same nonzero pattern as in the previous call
10261 
10262   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10263 
10264   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10265   actually needed.
10266 
10267   If you have many matrices with the same non-zero structure to multiply, you
10268   should use `MAT_REUSE_MATRIX` in all calls but the first
10269 
10270 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10271 @*/
10272 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10273 {
10274   PetscFunctionBegin;
10275   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10276   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10277 
10278   if (scall == MAT_INITIAL_MATRIX) {
10279     PetscCall(MatProductCreate(A, B, C, D));
10280     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10281     PetscCall(MatProductSetAlgorithm(*D, "default"));
10282     PetscCall(MatProductSetFill(*D, fill));
10283 
10284     (*D)->product->api_user = PETSC_TRUE;
10285     PetscCall(MatProductSetFromOptions(*D));
10286     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,
10287                ((PetscObject)C)->type_name);
10288     PetscCall(MatProductSymbolic(*D));
10289   } else { /* user may change input matrices when REUSE */
10290     PetscCall(MatProductReplaceMats(A, B, C, *D));
10291   }
10292   PetscCall(MatProductNumeric(*D));
10293   PetscFunctionReturn(PETSC_SUCCESS);
10294 }
10295 
10296 /*@
10297   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10298 
10299   Collective
10300 
10301   Input Parameters:
10302 + mat      - the matrix
10303 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10304 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10305 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10306 
10307   Output Parameter:
10308 . matredundant - redundant matrix
10309 
10310   Level: advanced
10311 
10312   Notes:
10313   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10314   original matrix has not changed from that last call to `MatCreateRedundantMatrix()`.
10315 
10316   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10317   calling it.
10318 
10319   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10320 
10321 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10322 @*/
10323 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10324 {
10325   MPI_Comm       comm;
10326   PetscMPIInt    size;
10327   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10328   Mat_Redundant *redund     = NULL;
10329   PetscSubcomm   psubcomm   = NULL;
10330   MPI_Comm       subcomm_in = subcomm;
10331   Mat           *matseq;
10332   IS             isrow, iscol;
10333   PetscBool      newsubcomm = PETSC_FALSE;
10334 
10335   PetscFunctionBegin;
10336   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10337   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10338     PetscAssertPointer(*matredundant, 5);
10339     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10340   }
10341 
10342   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10343   if (size == 1 || nsubcomm == 1) {
10344     if (reuse == MAT_INITIAL_MATRIX) {
10345       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10346     } else {
10347       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");
10348       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10349     }
10350     PetscFunctionReturn(PETSC_SUCCESS);
10351   }
10352 
10353   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10354   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10355   MatCheckPreallocated(mat, 1);
10356 
10357   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10358   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10359     /* create psubcomm, then get subcomm */
10360     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10361     PetscCallMPI(MPI_Comm_size(comm, &size));
10362     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10363 
10364     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10365     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10366     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10367     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10368     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10369     newsubcomm = PETSC_TRUE;
10370     PetscCall(PetscSubcommDestroy(&psubcomm));
10371   }
10372 
10373   /* get isrow, iscol and a local sequential matrix matseq[0] */
10374   if (reuse == MAT_INITIAL_MATRIX) {
10375     mloc_sub = PETSC_DECIDE;
10376     nloc_sub = PETSC_DECIDE;
10377     if (bs < 1) {
10378       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10379       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10380     } else {
10381       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10382       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10383     }
10384     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10385     rstart = rend - mloc_sub;
10386     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10387     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10388     PetscCall(ISSetIdentity(iscol));
10389   } else { /* reuse == MAT_REUSE_MATRIX */
10390     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");
10391     /* retrieve subcomm */
10392     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10393     redund = (*matredundant)->redundant;
10394     isrow  = redund->isrow;
10395     iscol  = redund->iscol;
10396     matseq = redund->matseq;
10397   }
10398   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10399 
10400   /* get matredundant over subcomm */
10401   if (reuse == MAT_INITIAL_MATRIX) {
10402     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10403 
10404     /* create a supporting struct and attach it to C for reuse */
10405     PetscCall(PetscNew(&redund));
10406     (*matredundant)->redundant = redund;
10407     redund->isrow              = isrow;
10408     redund->iscol              = iscol;
10409     redund->matseq             = matseq;
10410     if (newsubcomm) {
10411       redund->subcomm = subcomm;
10412     } else {
10413       redund->subcomm = MPI_COMM_NULL;
10414     }
10415   } else {
10416     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10417   }
10418 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10419   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10420     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10421     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10422   }
10423 #endif
10424   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10425   PetscFunctionReturn(PETSC_SUCCESS);
10426 }
10427 
10428 /*@C
10429   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10430   a given `Mat`. Each submatrix can span multiple procs.
10431 
10432   Collective
10433 
10434   Input Parameters:
10435 + mat     - the matrix
10436 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10437 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10438 
10439   Output Parameter:
10440 . subMat - parallel sub-matrices each spanning a given `subcomm`
10441 
10442   Level: advanced
10443 
10444   Notes:
10445   The submatrix partition across processors is dictated by `subComm` a
10446   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10447   is not restricted to be grouped with consecutive original MPI processes.
10448 
10449   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10450   map directly to the layout of the original matrix [wrt the local
10451   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10452   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10453   the `subMat`. However the offDiagMat looses some columns - and this is
10454   reconstructed with `MatSetValues()`
10455 
10456   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10457 
10458 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10459 @*/
10460 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10461 {
10462   PetscMPIInt commsize, subCommSize;
10463 
10464   PetscFunctionBegin;
10465   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10466   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10467   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10468 
10469   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");
10470   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10471   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10472   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10473   PetscFunctionReturn(PETSC_SUCCESS);
10474 }
10475 
10476 /*@
10477   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10478 
10479   Not Collective
10480 
10481   Input Parameters:
10482 + mat   - matrix to extract local submatrix from
10483 . isrow - local row indices for submatrix
10484 - iscol - local column indices for submatrix
10485 
10486   Output Parameter:
10487 . submat - the submatrix
10488 
10489   Level: intermediate
10490 
10491   Notes:
10492   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10493 
10494   Depending on the format of `mat`, the returned `submat` may not implement `MatMult()`.  Its communicator may be
10495   the same as `mat`, it may be `PETSC_COMM_SELF`, or some other sub-communictor of `mat`'s.
10496 
10497   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10498   `MatSetValuesBlockedLocal()` will also be implemented.
10499 
10500   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10501   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10502 
10503 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10504 @*/
10505 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10506 {
10507   PetscFunctionBegin;
10508   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10509   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10510   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10511   PetscCheckSameComm(isrow, 2, iscol, 3);
10512   PetscAssertPointer(submat, 4);
10513   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10514 
10515   if (mat->ops->getlocalsubmatrix) {
10516     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10517   } else {
10518     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10519   }
10520   PetscFunctionReturn(PETSC_SUCCESS);
10521 }
10522 
10523 /*@
10524   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10525 
10526   Not Collective
10527 
10528   Input Parameters:
10529 + mat    - matrix to extract local submatrix from
10530 . isrow  - local row indices for submatrix
10531 . iscol  - local column indices for submatrix
10532 - submat - the submatrix
10533 
10534   Level: intermediate
10535 
10536 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10537 @*/
10538 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10539 {
10540   PetscFunctionBegin;
10541   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10542   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10543   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10544   PetscCheckSameComm(isrow, 2, iscol, 3);
10545   PetscAssertPointer(submat, 4);
10546   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10547 
10548   if (mat->ops->restorelocalsubmatrix) {
10549     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10550   } else {
10551     PetscCall(MatDestroy(submat));
10552   }
10553   *submat = NULL;
10554   PetscFunctionReturn(PETSC_SUCCESS);
10555 }
10556 
10557 /*@
10558   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10559 
10560   Collective
10561 
10562   Input Parameter:
10563 . mat - the matrix
10564 
10565   Output Parameter:
10566 . is - if any rows have zero diagonals this contains the list of them
10567 
10568   Level: developer
10569 
10570 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10571 @*/
10572 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10573 {
10574   PetscFunctionBegin;
10575   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10576   PetscValidType(mat, 1);
10577   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10578   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10579 
10580   if (!mat->ops->findzerodiagonals) {
10581     Vec                diag;
10582     const PetscScalar *a;
10583     PetscInt          *rows;
10584     PetscInt           rStart, rEnd, r, nrow = 0;
10585 
10586     PetscCall(MatCreateVecs(mat, &diag, NULL));
10587     PetscCall(MatGetDiagonal(mat, diag));
10588     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10589     PetscCall(VecGetArrayRead(diag, &a));
10590     for (r = 0; r < rEnd - rStart; ++r)
10591       if (a[r] == 0.0) ++nrow;
10592     PetscCall(PetscMalloc1(nrow, &rows));
10593     nrow = 0;
10594     for (r = 0; r < rEnd - rStart; ++r)
10595       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10596     PetscCall(VecRestoreArrayRead(diag, &a));
10597     PetscCall(VecDestroy(&diag));
10598     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10599   } else {
10600     PetscUseTypeMethod(mat, findzerodiagonals, is);
10601   }
10602   PetscFunctionReturn(PETSC_SUCCESS);
10603 }
10604 
10605 /*@
10606   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10607 
10608   Collective
10609 
10610   Input Parameter:
10611 . mat - the matrix
10612 
10613   Output Parameter:
10614 . is - contains the list of rows with off block diagonal entries
10615 
10616   Level: developer
10617 
10618 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10619 @*/
10620 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10621 {
10622   PetscFunctionBegin;
10623   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10624   PetscValidType(mat, 1);
10625   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10626   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10627 
10628   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10629   PetscFunctionReturn(PETSC_SUCCESS);
10630 }
10631 
10632 /*@C
10633   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10634 
10635   Collective; No Fortran Support
10636 
10637   Input Parameter:
10638 . mat - the matrix
10639 
10640   Output Parameter:
10641 . values - the block inverses in column major order (FORTRAN-like)
10642 
10643   Level: advanced
10644 
10645   Notes:
10646   The size of the blocks is determined by the block size of the matrix.
10647 
10648   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10649 
10650   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10651 
10652 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10653 @*/
10654 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10655 {
10656   PetscFunctionBegin;
10657   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10658   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10659   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10660   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10661   PetscFunctionReturn(PETSC_SUCCESS);
10662 }
10663 
10664 /*@C
10665   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10666 
10667   Collective; No Fortran Support
10668 
10669   Input Parameters:
10670 + mat     - the matrix
10671 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10672 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10673 
10674   Output Parameter:
10675 . values - the block inverses in column major order (FORTRAN-like)
10676 
10677   Level: advanced
10678 
10679   Notes:
10680   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10681 
10682   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10683 
10684 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10685 @*/
10686 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10687 {
10688   PetscFunctionBegin;
10689   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10690   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10691   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10692   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10693   PetscFunctionReturn(PETSC_SUCCESS);
10694 }
10695 
10696 /*@
10697   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10698 
10699   Collective
10700 
10701   Input Parameters:
10702 + A - the matrix
10703 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10704 
10705   Level: advanced
10706 
10707   Note:
10708   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10709 
10710 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10711 @*/
10712 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10713 {
10714   const PetscScalar *vals;
10715   PetscInt          *dnnz;
10716   PetscInt           m, rstart, rend, bs, i, j;
10717 
10718   PetscFunctionBegin;
10719   PetscCall(MatInvertBlockDiagonal(A, &vals));
10720   PetscCall(MatGetBlockSize(A, &bs));
10721   PetscCall(MatGetLocalSize(A, &m, NULL));
10722   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10723   PetscCall(PetscMalloc1(m / bs, &dnnz));
10724   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10725   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10726   PetscCall(PetscFree(dnnz));
10727   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10728   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10729   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10730   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10731   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10732   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10733   PetscFunctionReturn(PETSC_SUCCESS);
10734 }
10735 
10736 /*@C
10737   MatTransposeColoringDestroy - Destroys a coloring context for matrix product $C = A*B^T$ that was created
10738   via `MatTransposeColoringCreate()`.
10739 
10740   Collective
10741 
10742   Input Parameter:
10743 . c - coloring context
10744 
10745   Level: intermediate
10746 
10747 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10748 @*/
10749 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10750 {
10751   MatTransposeColoring matcolor = *c;
10752 
10753   PetscFunctionBegin;
10754   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10755   if (--((PetscObject)matcolor)->refct > 0) {
10756     matcolor = NULL;
10757     PetscFunctionReturn(PETSC_SUCCESS);
10758   }
10759 
10760   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10761   PetscCall(PetscFree(matcolor->rows));
10762   PetscCall(PetscFree(matcolor->den2sp));
10763   PetscCall(PetscFree(matcolor->colorforcol));
10764   PetscCall(PetscFree(matcolor->columns));
10765   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10766   PetscCall(PetscHeaderDestroy(c));
10767   PetscFunctionReturn(PETSC_SUCCESS);
10768 }
10769 
10770 /*@C
10771   MatTransColoringApplySpToDen - Given a symbolic matrix product $C = A*B^T$ for which
10772   a `MatTransposeColoring` context has been created, computes a dense $B^T$ by applying
10773   `MatTransposeColoring` to sparse `B`.
10774 
10775   Collective
10776 
10777   Input Parameters:
10778 + coloring - coloring context created with `MatTransposeColoringCreate()`
10779 - B        - sparse matrix
10780 
10781   Output Parameter:
10782 . Btdense - dense matrix $B^T$
10783 
10784   Level: developer
10785 
10786   Note:
10787   These are used internally for some implementations of `MatRARt()`
10788 
10789 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10790 @*/
10791 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10792 {
10793   PetscFunctionBegin;
10794   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10795   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10796   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10797 
10798   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10799   PetscFunctionReturn(PETSC_SUCCESS);
10800 }
10801 
10802 /*@C
10803   MatTransColoringApplyDenToSp - Given a symbolic matrix product $C_{sp} = A*B^T$ for which
10804   a `MatTransposeColoring` context has been created and a dense matrix $C_{den} = A*B^T_{dense}$
10805   in which `B^T_{dens}` is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10806   $C_{sp}$ from $C_{den}$.
10807 
10808   Collective
10809 
10810   Input Parameters:
10811 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10812 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10813 
10814   Output Parameter:
10815 . Csp - sparse matrix
10816 
10817   Level: developer
10818 
10819   Note:
10820   These are used internally for some implementations of `MatRARt()`
10821 
10822 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10823 @*/
10824 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10825 {
10826   PetscFunctionBegin;
10827   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10828   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10829   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10830 
10831   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10832   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10833   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10834   PetscFunctionReturn(PETSC_SUCCESS);
10835 }
10836 
10837 /*@C
10838   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product $C = A*B^T$.
10839 
10840   Collective
10841 
10842   Input Parameters:
10843 + mat        - the matrix product C
10844 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10845 
10846   Output Parameter:
10847 . color - the new coloring context
10848 
10849   Level: intermediate
10850 
10851 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10852           `MatTransColoringApplyDenToSp()`
10853 @*/
10854 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10855 {
10856   MatTransposeColoring c;
10857   MPI_Comm             comm;
10858 
10859   PetscFunctionBegin;
10860   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10861   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10862   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10863 
10864   c->ctype = iscoloring->ctype;
10865   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10866 
10867   *color = c;
10868   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10869   PetscFunctionReturn(PETSC_SUCCESS);
10870 }
10871 
10872 /*@
10873   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10874   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10875   same, otherwise it will be larger
10876 
10877   Not Collective
10878 
10879   Input Parameter:
10880 . mat - the matrix
10881 
10882   Output Parameter:
10883 . state - the current state
10884 
10885   Level: intermediate
10886 
10887   Notes:
10888   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10889   different matrices
10890 
10891   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10892 
10893   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10894 
10895 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10896 @*/
10897 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10898 {
10899   PetscFunctionBegin;
10900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10901   *state = mat->nonzerostate;
10902   PetscFunctionReturn(PETSC_SUCCESS);
10903 }
10904 
10905 /*@
10906   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10907   matrices from each processor
10908 
10909   Collective
10910 
10911   Input Parameters:
10912 + comm   - the communicators the parallel matrix will live on
10913 . seqmat - the input sequential matrices
10914 . n      - number of local columns (or `PETSC_DECIDE`)
10915 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10916 
10917   Output Parameter:
10918 . mpimat - the parallel matrix generated
10919 
10920   Level: developer
10921 
10922   Note:
10923   The number of columns of the matrix in EACH processor MUST be the same.
10924 
10925 .seealso: [](ch_matrices), `Mat`
10926 @*/
10927 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10928 {
10929   PetscMPIInt size;
10930 
10931   PetscFunctionBegin;
10932   PetscCallMPI(MPI_Comm_size(comm, &size));
10933   if (size == 1) {
10934     if (reuse == MAT_INITIAL_MATRIX) {
10935       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10936     } else {
10937       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10938     }
10939     PetscFunctionReturn(PETSC_SUCCESS);
10940   }
10941 
10942   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");
10943 
10944   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10945   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10946   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10947   PetscFunctionReturn(PETSC_SUCCESS);
10948 }
10949 
10950 /*@
10951   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI processes' ownership ranges.
10952 
10953   Collective
10954 
10955   Input Parameters:
10956 + A - the matrix to create subdomains from
10957 - N - requested number of subdomains
10958 
10959   Output Parameters:
10960 + n   - number of subdomains resulting on this MPI process
10961 - iss - `IS` list with indices of subdomains on this MPI process
10962 
10963   Level: advanced
10964 
10965   Note:
10966   The number of subdomains must be smaller than the communicator size
10967 
10968 .seealso: [](ch_matrices), `Mat`, `IS`
10969 @*/
10970 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10971 {
10972   MPI_Comm    comm, subcomm;
10973   PetscMPIInt size, rank, color;
10974   PetscInt    rstart, rend, k;
10975 
10976   PetscFunctionBegin;
10977   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10978   PetscCallMPI(MPI_Comm_size(comm, &size));
10979   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10980   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);
10981   *n    = 1;
10982   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10983   color = rank / k;
10984   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10985   PetscCall(PetscMalloc1(1, iss));
10986   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10987   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10988   PetscCallMPI(MPI_Comm_free(&subcomm));
10989   PetscFunctionReturn(PETSC_SUCCESS);
10990 }
10991 
10992 /*@
10993   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10994 
10995   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10996   If they are not the same, uses `MatMatMatMult()`.
10997 
10998   Once the coarse grid problem is constructed, correct for interpolation operators
10999   that are not of full rank, which can legitimately happen in the case of non-nested
11000   geometric multigrid.
11001 
11002   Input Parameters:
11003 + restrct     - restriction operator
11004 . dA          - fine grid matrix
11005 . interpolate - interpolation operator
11006 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
11007 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
11008 
11009   Output Parameter:
11010 . A - the Galerkin coarse matrix
11011 
11012   Options Database Key:
11013 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
11014 
11015   Level: developer
11016 
11017 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
11018 @*/
11019 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
11020 {
11021   IS  zerorows;
11022   Vec diag;
11023 
11024   PetscFunctionBegin;
11025   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
11026   /* Construct the coarse grid matrix */
11027   if (interpolate == restrct) {
11028     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
11029   } else {
11030     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
11031   }
11032 
11033   /* If the interpolation matrix is not of full rank, A will have zero rows.
11034      This can legitimately happen in the case of non-nested geometric multigrid.
11035      In that event, we set the rows of the matrix to the rows of the identity,
11036      ignoring the equations (as the RHS will also be zero). */
11037 
11038   PetscCall(MatFindZeroRows(*A, &zerorows));
11039 
11040   if (zerorows != NULL) { /* if there are any zero rows */
11041     PetscCall(MatCreateVecs(*A, &diag, NULL));
11042     PetscCall(MatGetDiagonal(*A, diag));
11043     PetscCall(VecISSet(diag, zerorows, 1.0));
11044     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
11045     PetscCall(VecDestroy(&diag));
11046     PetscCall(ISDestroy(&zerorows));
11047   }
11048   PetscFunctionReturn(PETSC_SUCCESS);
11049 }
11050 
11051 /*@C
11052   MatSetOperation - Allows user to set a matrix operation for any matrix type
11053 
11054   Logically Collective
11055 
11056   Input Parameters:
11057 + mat - the matrix
11058 . op  - the name of the operation
11059 - f   - the function that provides the operation
11060 
11061   Level: developer
11062 
11063   Example Usage:
11064 .vb
11065   extern PetscErrorCode usermult(Mat, Vec, Vec);
11066 
11067   PetscCall(MatCreateXXX(comm, ..., &A));
11068   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFn *)usermult));
11069 .ve
11070 
11071   Notes:
11072   See the file `include/petscmat.h` for a complete list of matrix
11073   operations, which all have the form MATOP_<OPERATION>, where
11074   <OPERATION> is the name (in all capital letters) of the
11075   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11076 
11077   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
11078   sequence as the usual matrix interface routines, since they
11079   are intended to be accessed via the usual matrix interface
11080   routines, e.g.,
11081 .vb
11082   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
11083 .ve
11084 
11085   In particular each function MUST return `PETSC_SUCCESS` on success and
11086   nonzero on failure.
11087 
11088   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
11089 
11090 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11091 @*/
11092 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11093 {
11094   PetscFunctionBegin;
11095   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11096   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11097   (((void (**)(void))mat->ops)[op]) = f;
11098   PetscFunctionReturn(PETSC_SUCCESS);
11099 }
11100 
11101 /*@C
11102   MatGetOperation - Gets a matrix operation for any matrix type.
11103 
11104   Not Collective
11105 
11106   Input Parameters:
11107 + mat - the matrix
11108 - op  - the name of the operation
11109 
11110   Output Parameter:
11111 . f - the function that provides the operation
11112 
11113   Level: developer
11114 
11115   Example Usage:
11116 .vb
11117   PetscErrorCode (*usermult)(Mat, Vec, Vec);
11118 
11119   MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11120 .ve
11121 
11122   Notes:
11123   See the file include/petscmat.h for a complete list of matrix
11124   operations, which all have the form MATOP_<OPERATION>, where
11125   <OPERATION> is the name (in all capital letters) of the
11126   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11127 
11128   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11129 
11130 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11131 @*/
11132 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11133 {
11134   PetscFunctionBegin;
11135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11136   *f = (((void (**)(void))mat->ops)[op]);
11137   PetscFunctionReturn(PETSC_SUCCESS);
11138 }
11139 
11140 /*@
11141   MatHasOperation - Determines whether the given matrix supports the particular operation.
11142 
11143   Not Collective
11144 
11145   Input Parameters:
11146 + mat - the matrix
11147 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11148 
11149   Output Parameter:
11150 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11151 
11152   Level: advanced
11153 
11154   Note:
11155   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11156 
11157 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11158 @*/
11159 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11160 {
11161   PetscFunctionBegin;
11162   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11163   PetscAssertPointer(has, 3);
11164   if (mat->ops->hasoperation) {
11165     PetscUseTypeMethod(mat, hasoperation, op, has);
11166   } else {
11167     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11168     else {
11169       *has = PETSC_FALSE;
11170       if (op == MATOP_CREATE_SUBMATRIX) {
11171         PetscMPIInt size;
11172 
11173         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11174         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11175       }
11176     }
11177   }
11178   PetscFunctionReturn(PETSC_SUCCESS);
11179 }
11180 
11181 /*@
11182   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11183 
11184   Collective
11185 
11186   Input Parameter:
11187 . mat - the matrix
11188 
11189   Output Parameter:
11190 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11191 
11192   Level: beginner
11193 
11194 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11195 @*/
11196 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11197 {
11198   PetscFunctionBegin;
11199   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11200   PetscValidType(mat, 1);
11201   PetscAssertPointer(cong, 2);
11202   if (!mat->rmap || !mat->cmap) {
11203     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11204     PetscFunctionReturn(PETSC_SUCCESS);
11205   }
11206   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11207     PetscCall(PetscLayoutSetUp(mat->rmap));
11208     PetscCall(PetscLayoutSetUp(mat->cmap));
11209     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11210     if (*cong) mat->congruentlayouts = 1;
11211     else mat->congruentlayouts = 0;
11212   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11213   PetscFunctionReturn(PETSC_SUCCESS);
11214 }
11215 
11216 PetscErrorCode MatSetInf(Mat A)
11217 {
11218   PetscFunctionBegin;
11219   PetscUseTypeMethod(A, setinf);
11220   PetscFunctionReturn(PETSC_SUCCESS);
11221 }
11222 
11223 /*@C
11224   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
11225   and possibly removes small values from the graph structure.
11226 
11227   Collective
11228 
11229   Input Parameters:
11230 + A       - the matrix
11231 . sym     - `PETSC_TRUE` indicates that the graph should be symmetrized
11232 . scale   - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11233 . filter  - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11234 . num_idx - size of 'index' array
11235 - index   - array of block indices to use for graph strength of connection weight
11236 
11237   Output Parameter:
11238 . graph - the resulting graph
11239 
11240   Level: advanced
11241 
11242 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11243 @*/
11244 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, PetscInt num_idx, PetscInt index[], Mat *graph)
11245 {
11246   PetscFunctionBegin;
11247   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11248   PetscValidType(A, 1);
11249   PetscValidLogicalCollectiveBool(A, scale, 3);
11250   PetscAssertPointer(graph, 7);
11251   PetscUseTypeMethod(A, creategraph, sym, scale, filter, num_idx, index, graph);
11252   PetscFunctionReturn(PETSC_SUCCESS);
11253 }
11254 
11255 /*@
11256   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11257   meaning the same memory is used for the matrix, and no new memory is allocated.
11258 
11259   Collective
11260 
11261   Input Parameters:
11262 + A    - the matrix
11263 - 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
11264 
11265   Level: intermediate
11266 
11267   Developer Note:
11268   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11269   of the arrays in the data structure are unneeded.
11270 
11271 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatFilter()`
11272 @*/
11273 PetscErrorCode MatEliminateZeros(Mat A, PetscBool keep)
11274 {
11275   PetscFunctionBegin;
11276   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11277   PetscUseTypeMethod(A, eliminatezeros, keep);
11278   PetscFunctionReturn(PETSC_SUCCESS);
11279 }
11280