xref: /petsc/src/mat/interface/matrix.c (revision 697336901c45ac77e1fd620fe1fca906cf3f95c8)
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 locations it fills the locations with random numbers.
73 
74   It generates an error if used on 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()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130 @*/
131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
135   PetscValidRealPointer(pivot, 2);
136   PetscValidIntPointer(row, 3);
137   *pivot = mat->factorerror_zeropivot_value;
138   *row   = mat->factorerror_zeropivot_row;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*@
143   MatFactorGetError - gets the error code from a factorization
144 
145   Logically Collective
146 
147   Input Parameter:
148 . mat - the factored matrix
149 
150   Output Parameter:
151 . err - the error code
152 
153   Level: advanced
154 
155   Note:
156   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157 
158 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
159           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
160 @*/
161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
162 {
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
165   PetscValidPointer(err, 2);
166   *err = mat->factorerrortype;
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 /*@
171   MatFactorClearError - clears the error code in a factorization
172 
173   Logically Collective
174 
175   Input Parameter:
176 . mat - the factored matrix
177 
178   Level: developer
179 
180   Note:
181   This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
182 
183 .seealso: [](ch_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
184           `MatGetErrorCode()`, `MatFactorError`
185 @*/
186 PetscErrorCode MatFactorClearError(Mat mat)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
190   mat->factorerrortype             = MAT_FACTOR_NOERROR;
191   mat->factorerror_zeropivot_value = 0.0;
192   mat->factorerror_zeropivot_row   = 0;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
197 {
198   Vec                r, l;
199   const PetscScalar *al;
200   PetscInt           i, nz, gnz, N, n;
201 
202   PetscFunctionBegin;
203   PetscCall(MatCreateVecs(mat, &r, &l));
204   if (!cols) { /* nonzero rows */
205     PetscCall(MatGetSize(mat, &N, NULL));
206     PetscCall(MatGetLocalSize(mat, &n, NULL));
207     PetscCall(VecSet(l, 0.0));
208     PetscCall(VecSetRandom(r, NULL));
209     PetscCall(MatMult(mat, r, l));
210     PetscCall(VecGetArrayRead(l, &al));
211   } else { /* nonzero columns */
212     PetscCall(MatGetSize(mat, NULL, &N));
213     PetscCall(MatGetLocalSize(mat, NULL, &n));
214     PetscCall(VecSet(r, 0.0));
215     PetscCall(VecSetRandom(l, NULL));
216     PetscCall(MatMultTranspose(mat, l, r));
217     PetscCall(VecGetArrayRead(r, &al));
218   }
219   if (tol <= 0.0) {
220     for (i = 0, nz = 0; i < n; i++)
221       if (al[i] != 0.0) nz++;
222   } else {
223     for (i = 0, nz = 0; i < n; i++)
224       if (PetscAbsScalar(al[i]) > tol) nz++;
225   }
226   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
227   if (gnz != N) {
228     PetscInt *nzr;
229     PetscCall(PetscMalloc1(nz, &nzr));
230     if (nz) {
231       if (tol < 0) {
232         for (i = 0, nz = 0; i < n; i++)
233           if (al[i] != 0.0) nzr[nz++] = i;
234       } else {
235         for (i = 0, nz = 0; i < n; i++)
236           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
237       }
238     }
239     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
240   } else *nonzero = NULL;
241   if (!cols) { /* nonzero rows */
242     PetscCall(VecRestoreArrayRead(l, &al));
243   } else {
244     PetscCall(VecRestoreArrayRead(r, &al));
245   }
246   PetscCall(VecDestroy(&l));
247   PetscCall(VecDestroy(&r));
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@
252   MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
253 
254   Input Parameter:
255 . mat - the matrix
256 
257   Output Parameter:
258 . keptrows - the rows that are not completely zero
259 
260   Level: intermediate
261 
262   Note:
263   `keptrows` is set to `NULL` if all rows are nonzero.
264 
265 .seealso: [](ch_matrices), `Mat`, `MatFindZeroRows()`
266  @*/
267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
268 {
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
271   PetscValidType(mat, 1);
272   PetscValidPointer(keptrows, 2);
273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
275   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
276   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281   MatFindZeroRows - Locate all rows that are completely zero in the matrix
282 
283   Input Parameter:
284 . mat - the matrix
285 
286   Output Parameter:
287 . zerorows - the rows that are completely zero
288 
289   Level: intermediate
290 
291   Note:
292   `zerorows` is set to `NULL` if no rows are zero.
293 
294 .seealso: [](ch_matrices), `Mat`, `MatFindNonzeroRows()`
295  @*/
296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
297 {
298   IS       keptrows;
299   PetscInt m, n;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
303   PetscValidType(mat, 1);
304   PetscValidPointer(zerorows, 2);
305   PetscCall(MatFindNonzeroRows(mat, &keptrows));
306   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
307      In keeping with this convention, we set zerorows to NULL if there are no zero
308      rows. */
309   if (keptrows == NULL) {
310     *zerorows = NULL;
311   } else {
312     PetscCall(MatGetOwnershipRange(mat, &m, &n));
313     PetscCall(ISComplement(keptrows, m, n, zerorows));
314     PetscCall(ISDestroy(&keptrows));
315   }
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@
320   MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
321 
322   Not Collective
323 
324   Input Parameter:
325 . A - the matrix
326 
327   Output Parameter:
328 . a - the diagonal part (which is a SEQUENTIAL matrix)
329 
330   Level: advanced
331 
332   Notes:
333   See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
334 
335   Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
336 
337 .seealso: [](ch_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
338 @*/
339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
343   PetscValidType(A, 1);
344   PetscValidPointer(a, 2);
345   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
346   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
347   else {
348     PetscMPIInt size;
349 
350     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
351     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
352     *a = A;
353   }
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358   MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
359 
360   Collective
361 
362   Input Parameter:
363 . mat - the matrix
364 
365   Output Parameter:
366 . trace - the sum of the diagonal entries
367 
368   Level: advanced
369 
370 .seealso: [](ch_matrices), `Mat`
371 @*/
372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
373 {
374   Vec diag;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
378   PetscValidScalarPointer(trace, 2);
379   PetscCall(MatCreateVecs(mat, &diag, NULL));
380   PetscCall(MatGetDiagonal(mat, diag));
381   PetscCall(VecSum(diag, trace));
382   PetscCall(VecDestroy(&diag));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@
387   MatRealPart - Zeros out the imaginary part of the matrix
388 
389   Logically Collective
390 
391   Input Parameter:
392 . mat - the matrix
393 
394   Level: advanced
395 
396 .seealso: [](ch_matrices), `Mat`, `MatImaginaryPart()`
397 @*/
398 PetscErrorCode MatRealPart(Mat mat)
399 {
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
402   PetscValidType(mat, 1);
403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
404   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405   MatCheckPreallocated(mat, 1);
406   PetscUseTypeMethod(mat, realpart);
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411   MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
412 
413   Collective
414 
415   Input Parameter:
416 . mat - the matrix
417 
418   Output Parameters:
419 + nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
420 - ghosts  - the global indices of the ghost points
421 
422   Level: advanced
423 
424   Note:
425   `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
426 
427 .seealso: [](ch_matrices), `Mat`, `VecCreateGhost()`
428 @*/
429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
430 {
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
433   PetscValidType(mat, 1);
434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
436   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
437   else {
438     if (nghosts) *nghosts = 0;
439     if (ghosts) *ghosts = NULL;
440   }
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445   MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
446 
447   Logically Collective
448 
449   Input Parameter:
450 . mat - the matrix
451 
452   Level: advanced
453 
454 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`
455 @*/
456 PetscErrorCode MatImaginaryPart(Mat mat)
457 {
458   PetscFunctionBegin;
459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
460   PetscValidType(mat, 1);
461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
463   MatCheckPreallocated(mat, 1);
464   PetscUseTypeMethod(mat, imaginarypart);
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*@
469   MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
470 
471   Not Collective
472 
473   Input Parameter:
474 . mat - the matrix
475 
476   Output Parameters:
477 + missing - is any diagonal missing
478 - dd      - first diagonal entry that is missing (optional) on this process
479 
480   Level: advanced
481 
482 .seealso: [](ch_matrices), `Mat`
483 @*/
484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
488   PetscValidType(mat, 1);
489   PetscValidBoolPointer(missing, 2);
490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
492   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
493   PetscFunctionReturn(PETSC_SUCCESS);
494 }
495 
496 /*@C
497   MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
498   for each row that you get to ensure that your application does
499   not bleed memory.
500 
501   Not Collective
502 
503   Input Parameters:
504 + mat - the matrix
505 - row - the row to get
506 
507   Output Parameters:
508 + ncols - if not `NULL`, the number of nonzeros in the row
509 . cols  - if not `NULL`, the column numbers
510 - vals  - if not `NULL`, the values
511 
512   Level: advanced
513 
514   Notes:
515   This routine is provided for people who need to have direct access
516   to the structure of a matrix.  We hope that we provide enough
517   high-level matrix routines that few users will need it.
518 
519   `MatGetRow()` always returns 0-based column indices, regardless of
520   whether the internal representation is 0-based (default) or 1-based.
521 
522   For better efficiency, set cols and/or vals to `NULL` if you do
523   not wish to extract these quantities.
524 
525   The user can only examine the values extracted with `MatGetRow()`;
526   the values cannot be altered.  To change the matrix entries, one
527   must use `MatSetValues()`.
528 
529   You can only have one call to `MatGetRow()` outstanding for a particular
530   matrix at a time, per processor. `MatGetRow()` can only obtain rows
531   associated with the given processor, it cannot get rows from the
532   other processors; for that we suggest using `MatCreateSubMatrices()`, then
533   MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
534   is in the global number of rows.
535 
536   Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
537 
538   Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
539 
540   Fortran Notes:
541   The calling sequence is
542 .vb
543    MatGetRow(matrix,row,ncols,cols,values,ierr)
544          Mat     matrix (input)
545          integer row    (input)
546          integer ncols  (output)
547          integer cols(maxcols) (output)
548          double precision (or double complex) values(maxcols) output
549 .ve
550   where maxcols >= maximum nonzeros in any row of the matrix.
551 
552   Caution:
553   Do not try to change the contents of the output arrays (`cols` and `vals`).
554   In some cases, this may corrupt the matrix.
555 
556 .seealso: [](ch_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
557 @*/
558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
559 {
560   PetscInt incols;
561 
562   PetscFunctionBegin;
563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
564   PetscValidType(mat, 1);
565   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
566   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
567   MatCheckPreallocated(mat, 1);
568   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);
569   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
570   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
571   if (ncols) *ncols = incols;
572   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
573   PetscFunctionReturn(PETSC_SUCCESS);
574 }
575 
576 /*@
577   MatConjugate - replaces the matrix values with their complex conjugates
578 
579   Logically Collective
580 
581   Input Parameter:
582 . mat - the matrix
583 
584   Level: advanced
585 
586 .seealso: [](ch_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
587 @*/
588 PetscErrorCode MatConjugate(Mat mat)
589 {
590   PetscFunctionBegin;
591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
593   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
594     PetscUseTypeMethod(mat, conjugate);
595     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
596   }
597   PetscFunctionReturn(PETSC_SUCCESS);
598 }
599 
600 /*@C
601   MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
602 
603   Not Collective
604 
605   Input Parameters:
606 + mat   - the matrix
607 . row   - the row to get
608 . ncols - the number of nonzeros
609 . cols  - the columns of the nonzeros
610 - vals  - if nonzero the column values
611 
612   Level: advanced
613 
614   Notes:
615   This routine should be called after you have finished examining the entries.
616 
617   This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
618   us of the array after it has been restored. If you pass `NULL`, it will
619   not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
620 
621   Fortran Notes:
622   The calling sequence is
623 .vb
624    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
625       Mat     matrix (input)
626       integer row    (input)
627       integer ncols  (output)
628       integer cols(maxcols) (output)
629       double precision (or double complex) values(maxcols) output
630 .ve
631   Where maxcols >= maximum nonzeros in any row of the matrix.
632 
633   In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
634   before another call to `MatGetRow()` can be made.
635 
636 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`
637 @*/
638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
639 {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   if (ncols) PetscValidIntPointer(ncols, 3);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
645   PetscUseTypeMethod(mat, restorerow, row, ncols, (PetscInt **)cols, (PetscScalar **)vals);
646   if (ncols) *ncols = 0;
647   if (cols) *cols = NULL;
648   if (vals) *vals = NULL;
649   PetscFunctionReturn(PETSC_SUCCESS);
650 }
651 
652 /*@
653   MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
654   You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
655 
656   Not Collective
657 
658   Input Parameter:
659 . mat - the matrix
660 
661   Level: advanced
662 
663   Note:
664   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.
665 
666 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
667 @*/
668 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
669 {
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
672   PetscValidType(mat, 1);
673   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
674   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
675   MatCheckPreallocated(mat, 1);
676   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
677   PetscUseTypeMethod(mat, getrowuppertriangular);
678   PetscFunctionReturn(PETSC_SUCCESS);
679 }
680 
681 /*@
682   MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683 
684   Not Collective
685 
686   Input Parameter:
687 . mat - the matrix
688 
689   Level: advanced
690 
691   Note:
692   This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
693 
694 .seealso: [](ch_matrices), `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
705   PetscUseTypeMethod(mat, restorerowuppertriangular);
706   PetscFunctionReturn(PETSC_SUCCESS);
707 }
708 
709 /*@C
710   MatSetOptionsPrefix - Sets the prefix used for searching for all
711   `Mat` options in the database.
712 
713   Logically Collective
714 
715   Input Parameters:
716 + A      - the matrix
717 - prefix - the prefix to prepend to all option names
718 
719   Level: advanced
720 
721   Notes:
722   A hyphen (-) must NOT be given at the beginning of the prefix name.
723   The first character of all runtime options is AUTOMATICALLY the hyphen.
724 
725   This is NOT used for options for the factorization of the matrix. Normally the
726   prefix is automatically passed in from the PC calling the factorization. To set
727   it directly use  `MatSetOptionsPrefixFactor()`
728 
729 .seealso: [](ch_matrices), `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
730 @*/
731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
732 {
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
735   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
736   PetscFunctionReturn(PETSC_SUCCESS);
737 }
738 
739 /*@C
740   MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
741   for matrices created with `MatGetFactor()`
742 
743   Logically Collective
744 
745   Input Parameters:
746 + A      - the matrix
747 - prefix - the prefix to prepend to all option names for the factored matrix
748 
749   Level: developer
750 
751   Notes:
752   A hyphen (-) must NOT be given at the beginning of the prefix name.
753   The first character of all runtime options is AUTOMATICALLY the hyphen.
754 
755   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
756   it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: [](ch_matrices), `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   if (prefix) {
765     PetscValidCharPointer(prefix, 2);
766     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
767     if (prefix != A->factorprefix) {
768       PetscCall(PetscFree(A->factorprefix));
769       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
770     }
771   } else PetscCall(PetscFree(A->factorprefix));
772   PetscFunctionReturn(PETSC_SUCCESS);
773 }
774 
775 /*@C
776   MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
777   for matrices created with `MatGetFactor()`
778 
779   Logically Collective
780 
781   Input Parameters:
782 + A      - the matrix
783 - prefix - the prefix to prepend to all option names for the factored matrix
784 
785   Level: developer
786 
787   Notes:
788   A hyphen (-) must NOT be given at the beginning of the prefix name.
789   The first character of all runtime options is AUTOMATICALLY the hyphen.
790 
791   Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
792   it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
793 
794 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
795           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
796           `MatSetOptionsPrefix()`
797 @*/
798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
799 {
800   size_t len1, len2, new_len;
801 
802   PetscFunctionBegin;
803   PetscValidHeader(A, 1);
804   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
805   if (!A->factorprefix) {
806     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
807     PetscFunctionReturn(PETSC_SUCCESS);
808   }
809   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
810 
811   PetscCall(PetscStrlen(A->factorprefix, &len1));
812   PetscCall(PetscStrlen(prefix, &len2));
813   new_len = len1 + len2 + 1;
814   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
815   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
816   PetscFunctionReturn(PETSC_SUCCESS);
817 }
818 
819 /*@C
820   MatAppendOptionsPrefix - Appends to the prefix used for searching for all
821   matrix options in the database.
822 
823   Logically Collective
824 
825   Input Parameters:
826 + A      - the matrix
827 - prefix - the prefix to prepend to all option names
828 
829   Level: advanced
830 
831   Note:
832   A hyphen (-) must NOT be given at the beginning of the prefix name.
833   The first character of all runtime options is AUTOMATICALLY the hyphen.
834 
835 .seealso: [](ch_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
836 @*/
837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
838 {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
842   PetscFunctionReturn(PETSC_SUCCESS);
843 }
844 
845 /*@C
846   MatGetOptionsPrefix - Gets the prefix used for searching for all
847   matrix options in the database.
848 
849   Not Collective
850 
851   Input Parameter:
852 . A - the matrix
853 
854   Output Parameter:
855 . prefix - pointer to the prefix string used
856 
857   Level: advanced
858 
859   Fortran Notes:
860   The user should pass in a string `prefix` of
861   sufficient length to hold the prefix.
862 
863 .seealso: [](ch_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
864 @*/
865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
866 {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
869   PetscValidPointer(prefix, 2);
870   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
871   PetscFunctionReturn(PETSC_SUCCESS);
872 }
873 
874 /*@
875   MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
876 
877   Collective
878 
879   Input Parameter:
880 . A - the matrix
881 
882   Level: beginner
883 
884   Notes:
885   The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
886 
887   Users can reset the preallocation to access the original memory.
888 
889   Currently only supported for  `MATAIJ` matrices.
890 
891 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
892 @*/
893 PetscErrorCode MatResetPreallocation(Mat A)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   PetscValidType(A, 1);
898   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()");
899   if (A->num_ass == 0) PetscFunctionReturn(PETSC_SUCCESS);
900   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
901   PetscFunctionReturn(PETSC_SUCCESS);
902 }
903 
904 /*@
905   MatSetUp - Sets up the internal matrix data structures for later use.
906 
907   Collective
908 
909   Input Parameter:
910 . A - the matrix
911 
912   Level: intermediate
913 
914   Notes:
915   If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
916   setting values in the matrix.
917 
918   If a suitable preallocation routine is used, this function does not need to be called.
919 
920   This routine is called internally by other matrix functions when needed so rarely needs to be called by users
921 
922 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
923 @*/
924 PetscErrorCode MatSetUp(Mat A)
925 {
926   PetscFunctionBegin;
927   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
928   if (!((PetscObject)A)->type_name) {
929     PetscMPIInt size;
930 
931     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
932     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
933   }
934   if (!A->preallocated) PetscTryTypeMethod(A, setup);
935   PetscCall(PetscLayoutSetUp(A->rmap));
936   PetscCall(PetscLayoutSetUp(A->cmap));
937   A->preallocated = PETSC_TRUE;
938   PetscFunctionReturn(PETSC_SUCCESS);
939 }
940 
941 #if defined(PETSC_HAVE_SAWS)
942   #include <petscviewersaws.h>
943 #endif
944 
945 /*
946    If threadsafety is on extraneous matrices may be printed
947 
948    This flag cannot be stored in the matrix because the original matrix in MatView() may assemble a new matrix which is passed into MatViewFromOptions()
949 */
950 #if !defined(PETSC_HAVE_THREADSAFETY)
951 static PetscInt insidematview = 0;
952 #endif
953 
954 /*@C
955   MatViewFromOptions - View properties of the matrix based on options set in the options database
956 
957   Collective
958 
959   Input Parameters:
960 + A    - the matrix
961 . obj  - optional additional object that provides the options prefix to use
962 - name - command line option
963 
964   Options Database Key:
965 . -mat_view [viewertype]:... - the viewer and its options
966 
967   Level: intermediate
968 
969   Notes:
970 .vb
971     If no value is provided ascii:stdout is used
972        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
973                                                   for example ascii::ascii_info prints just the information about the object not all details
974                                                   unless :append is given filename opens in write mode, overwriting what was already there
975        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
976        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
977        socket[:port]                             defaults to the standard output port
978        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
979 .ve
980 
981 .seealso: [](ch_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
982 @*/
983 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
984 {
985   PetscFunctionBegin;
986   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
987 #if !defined(PETSC_HAVE_THREADSAFETY)
988   if (insidematview) PetscFunctionReturn(PETSC_SUCCESS);
989 #endif
990   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
991   PetscFunctionReturn(PETSC_SUCCESS);
992 }
993 
994 /*@C
995   MatView - display information about a matrix in a variety ways
996 
997   Collective
998 
999   Input Parameters:
1000 + mat    - the matrix
1001 - viewer - visualization context
1002 
1003   Options Database Keys:
1004 + -mat_view ::ascii_info           - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1005 . -mat_view ::ascii_info_detail    - Prints more detailed info
1006 . -mat_view                        - Prints matrix in ASCII format
1007 . -mat_view ::ascii_matlab         - Prints matrix in Matlab format
1008 . -mat_view draw                   - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1009 . -display <name>                  - Sets display name (default is host)
1010 . -draw_pause <sec>                - Sets number of seconds to pause after display
1011 . -mat_view socket                 - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1012 . -viewer_socket_machine <machine> - -
1013 . -viewer_socket_port <port>       - -
1014 . -mat_view binary                 - save matrix to file in binary format
1015 - -viewer_binary_filename <name>   - -
1016 
1017   Level: beginner
1018 
1019   Notes:
1020   The available visualization contexts include
1021 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1022 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1023 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1024 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1025 
1026   The user can open alternative visualization contexts with
1027 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1028 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1029   specified file; corresponding input uses `MatLoad()`
1030 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1031   an X window display
1032 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1033   Currently only the `MATSEQDENSE` and `MATAIJ`
1034   matrix types support the Socket viewer.
1035 
1036   The user can call `PetscViewerPushFormat()` to specify the output
1037   format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1038   `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1039 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1040 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1041 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1042 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1043   format common among all matrix types
1044 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1045   format (which is in many cases the same as the default)
1046 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1047   size and structure (not the matrix entries)
1048 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1049   the matrix structure
1050 
1051   The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1052   the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1053 
1054   In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1055 
1056   See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1057   viewer is used.
1058 
1059   See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1060   viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1061 
1062   One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1063   and then use the following mouse functions.
1064 .vb
1065   left mouse: zoom in
1066   middle mouse: zoom out
1067   right mouse: continue with the simulation
1068 .ve
1069 
1070 .seealso: [](ch_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1071           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1072 @*/
1073 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1074 {
1075   PetscInt          rows, cols, rbs, cbs;
1076   PetscBool         isascii, isstring, issaws;
1077   PetscViewerFormat format;
1078   PetscMPIInt       size;
1079 
1080   PetscFunctionBegin;
1081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1082   PetscValidType(mat, 1);
1083   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1084   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1085   PetscCheckSameComm(mat, 1, viewer, 2);
1086 
1087   PetscCall(PetscViewerGetFormat(viewer, &format));
1088   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1089   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1090 
1091 #if !defined(PETSC_HAVE_THREADSAFETY)
1092   insidematview++;
1093 #endif
1094   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1095   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1096   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1097   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");
1098 
1099   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1100   if (isascii) {
1101     if (!mat->preallocated) {
1102       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1103 #if !defined(PETSC_HAVE_THREADSAFETY)
1104       insidematview--;
1105 #endif
1106       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1107       PetscFunctionReturn(PETSC_SUCCESS);
1108     }
1109     if (!mat->assembled) {
1110       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1111 #if !defined(PETSC_HAVE_THREADSAFETY)
1112       insidematview--;
1113 #endif
1114       PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1115       PetscFunctionReturn(PETSC_SUCCESS);
1116     }
1117     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1118     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1119       MatNullSpace nullsp, transnullsp;
1120 
1121       PetscCall(PetscViewerASCIIPushTab(viewer));
1122       PetscCall(MatGetSize(mat, &rows, &cols));
1123       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1124       if (rbs != 1 || cbs != 1) {
1125         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1126         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1127       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1128       if (mat->factortype) {
1129         MatSolverType solver;
1130         PetscCall(MatFactorGetSolverType(mat, &solver));
1131         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1132       }
1133       if (mat->ops->getinfo) {
1134         MatInfo info;
1135         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1136         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1137         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1138       }
1139       PetscCall(MatGetNullSpace(mat, &nullsp));
1140       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1141       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1142       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1143       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1144       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1145       PetscCall(PetscViewerASCIIPushTab(viewer));
1146       PetscCall(MatProductView(mat, viewer));
1147       PetscCall(PetscViewerASCIIPopTab(viewer));
1148     }
1149   } else if (issaws) {
1150 #if defined(PETSC_HAVE_SAWS)
1151     PetscMPIInt rank;
1152 
1153     PetscCall(PetscObjectName((PetscObject)mat));
1154     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1155     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1156 #endif
1157   } else if (isstring) {
1158     const char *type;
1159     PetscCall(MatGetType(mat, &type));
1160     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1161     PetscTryTypeMethod(mat, view, viewer);
1162   }
1163   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1164     PetscCall(PetscViewerASCIIPushTab(viewer));
1165     PetscUseTypeMethod(mat, viewnative, viewer);
1166     PetscCall(PetscViewerASCIIPopTab(viewer));
1167   } else if (mat->ops->view) {
1168     PetscCall(PetscViewerASCIIPushTab(viewer));
1169     PetscUseTypeMethod(mat, view, viewer);
1170     PetscCall(PetscViewerASCIIPopTab(viewer));
1171   }
1172   if (isascii) {
1173     PetscCall(PetscViewerGetFormat(viewer, &format));
1174     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1175   }
1176   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1177 #if !defined(PETSC_HAVE_THREADSAFETY)
1178   insidematview--;
1179 #endif
1180   PetscFunctionReturn(PETSC_SUCCESS);
1181 }
1182 
1183 #if defined(PETSC_USE_DEBUG)
1184   #include <../src/sys/totalview/tv_data_display.h>
1185 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1186 {
1187   TV_add_row("Local rows", "int", &mat->rmap->n);
1188   TV_add_row("Local columns", "int", &mat->cmap->n);
1189   TV_add_row("Global rows", "int", &mat->rmap->N);
1190   TV_add_row("Global columns", "int", &mat->cmap->N);
1191   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1192   return TV_format_OK;
1193 }
1194 #endif
1195 
1196 /*@C
1197   MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1198   with `MatView()`.  The matrix format is determined from the options database.
1199   Generates a parallel MPI matrix if the communicator has more than one
1200   processor.  The default matrix type is `MATAIJ`.
1201 
1202   Collective
1203 
1204   Input Parameters:
1205 + mat    - the newly loaded matrix, this needs to have been created with `MatCreate()`
1206             or some related function before a call to `MatLoad()`
1207 - viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1208 
1209   Options Database Keys:
1210    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1211    block size
1212 . -matload_block_size <bs> - set block size
1213 
1214   Level: beginner
1215 
1216   Notes:
1217   If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1218   `Mat` before calling this routine if you wish to set it from the options database.
1219 
1220   `MatLoad()` automatically loads into the options database any options
1221   given in the file filename.info where filename is the name of the file
1222   that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1223   file will be ignored if you use the -viewer_binary_skip_info option.
1224 
1225   If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1226   sets the default matrix type AIJ and sets the local and global sizes.
1227   If type and/or size is already set, then the same are used.
1228 
1229   In parallel, each processor can load a subset of rows (or the
1230   entire matrix).  This routine is especially useful when a large
1231   matrix is stored on disk and only part of it is desired on each
1232   processor.  For example, a parallel solver may access only some of
1233   the rows from each processor.  The algorithm used here reads
1234   relatively small blocks of data rather than reading the entire
1235   matrix and then subsetting it.
1236 
1237   Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1238   Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1239   or the sequence like
1240 .vb
1241     `PetscViewer` v;
1242     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1243     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1244     `PetscViewerSetFromOptions`(v);
1245     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1246     `PetscViewerFileSetName`(v,"datafile");
1247 .ve
1248   The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1249 $ -viewer_type {binary, hdf5}
1250 
1251   See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1252   and src/mat/tutorials/ex10.c with the second approach.
1253 
1254   In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1255   is read onto MPI rank 0 and then shipped to its destination MPI rank, one after another.
1256   Multiple objects, both matrices and vectors, can be stored within the same file.
1257   Their `PetscObject` name is ignored; they are loaded in the order of their storage.
1258 
1259   Most users should not need to know the details of the binary storage
1260   format, since `MatLoad()` and `MatView()` completely hide these details.
1261   But for anyone who is interested, the standard binary matrix storage
1262   format is
1263 
1264 .vb
1265     PetscInt    MAT_FILE_CLASSID
1266     PetscInt    number of rows
1267     PetscInt    number of columns
1268     PetscInt    total number of nonzeros
1269     PetscInt    *number nonzeros in each row
1270     PetscInt    *column indices of all nonzeros (starting index is zero)
1271     PetscScalar *values of all nonzeros
1272 .ve
1273   If PETSc was not configured with `--with-64-bit-indices` then only `MATMPIAIJ` matrices with more than `PETSC_INT_MAX` non-zeros can be
1274   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
1275   case will not fit in a (32-bit) `PetscInt` the value `PETSC_INT_MAX` is used for the header entry `total number of nonzeros`.
1276 
1277   PETSc automatically does the byte swapping for
1278   machines that store the bytes reversed. Thus if you write your own binary
1279   read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1280   and `PetscBinaryWrite()` to see how this may be done.
1281 
1282   In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1283   Each processor's chunk is loaded independently by its owning MPI process.
1284   Multiple objects, both matrices and vectors, can be stored within the same file.
1285   They are looked up by their PetscObject name.
1286 
1287   As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1288   by default the same structure and naming of the AIJ arrays and column count
1289   within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1290 $    save example.mat A b -v7.3
1291   can be directly read by this routine (see Reference 1 for details).
1292 
1293   Depending on your MATLAB version, this format might be a default,
1294   otherwise you can set it as default in Preferences.
1295 
1296   Unless -nocompression flag is used to save the file in MATLAB,
1297   PETSc must be configured with ZLIB package.
1298 
1299   See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1300 
1301   This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1302 
1303   Corresponding `MatView()` is not yet implemented.
1304 
1305   The loaded matrix is actually a transpose of the original one in MATLAB,
1306   unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1307   With this format, matrix is automatically transposed by PETSc,
1308   unless the matrix is marked as SPD or symmetric
1309   (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1310 
1311   References:
1312 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1313 
1314 .seealso: [](ch_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1315  @*/
1316 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1317 {
1318   PetscBool flg;
1319 
1320   PetscFunctionBegin;
1321   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1322   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1323 
1324   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1325 
1326   flg = PETSC_FALSE;
1327   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1328   if (flg) {
1329     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1330     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1331   }
1332   flg = PETSC_FALSE;
1333   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1334   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1335 
1336   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1337   PetscUseTypeMethod(mat, load, viewer);
1338   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1339   PetscFunctionReturn(PETSC_SUCCESS);
1340 }
1341 
1342 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1343 {
1344   Mat_Redundant *redund = *redundant;
1345 
1346   PetscFunctionBegin;
1347   if (redund) {
1348     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1349       PetscCall(ISDestroy(&redund->isrow));
1350       PetscCall(ISDestroy(&redund->iscol));
1351       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1352     } else {
1353       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1354       PetscCall(PetscFree(redund->sbuf_j));
1355       PetscCall(PetscFree(redund->sbuf_a));
1356       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1357         PetscCall(PetscFree(redund->rbuf_j[i]));
1358         PetscCall(PetscFree(redund->rbuf_a[i]));
1359       }
1360       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1361     }
1362 
1363     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1364     PetscCall(PetscFree(redund));
1365   }
1366   PetscFunctionReturn(PETSC_SUCCESS);
1367 }
1368 
1369 /*@C
1370   MatDestroy - Frees space taken by a matrix.
1371 
1372   Collective
1373 
1374   Input Parameter:
1375 . A - the matrix
1376 
1377   Level: beginner
1378 
1379   Developer Notes:
1380   Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1381   `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1382   `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1383   if changes are needed here.
1384 
1385 .seealso: [](ch_matrices), `Mat`, `MatCreate()`
1386 @*/
1387 PetscErrorCode MatDestroy(Mat *A)
1388 {
1389   PetscFunctionBegin;
1390   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1391   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1392   if (--((PetscObject)(*A))->refct > 0) {
1393     *A = NULL;
1394     PetscFunctionReturn(PETSC_SUCCESS);
1395   }
1396 
1397   /* if memory was published with SAWs then destroy it */
1398   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1399   PetscTryTypeMethod((*A), destroy);
1400 
1401   PetscCall(PetscFree((*A)->factorprefix));
1402   PetscCall(PetscFree((*A)->defaultvectype));
1403   PetscCall(PetscFree((*A)->defaultrandtype));
1404   PetscCall(PetscFree((*A)->bsizes));
1405   PetscCall(PetscFree((*A)->solvertype));
1406   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1407   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1408   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1409   PetscCall(MatProductClear(*A));
1410   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1411   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1412   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1413   PetscCall(MatDestroy(&(*A)->schur));
1414   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1415   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1416   PetscCall(PetscHeaderDestroy(A));
1417   PetscFunctionReturn(PETSC_SUCCESS);
1418 }
1419 
1420 /*@C
1421   MatSetValues - Inserts or adds a block of values into a matrix.
1422   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1423   MUST be called after all calls to `MatSetValues()` have been completed.
1424 
1425   Not Collective
1426 
1427   Input Parameters:
1428 + mat  - the matrix
1429 . v    - a logically two-dimensional array of values
1430 . m    - the number of rows
1431 . idxm - the global indices of the rows
1432 . n    - the number of columns
1433 . idxn - the global indices of the columns
1434 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1435 
1436   Level: beginner
1437 
1438   Notes:
1439   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1440 
1441   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1442   options cannot be mixed without intervening calls to the assembly
1443   routines.
1444 
1445   `MatSetValues()` uses 0-based row and column numbers in Fortran
1446   as well as in C.
1447 
1448   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1449   simply ignored. This allows easily inserting element stiffness matrices
1450   with homogeneous Dirchlet boundary conditions that you don't want represented
1451   in the matrix.
1452 
1453   Efficiency Alert:
1454   The routine `MatSetValuesBlocked()` may offer much better efficiency
1455   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1456 
1457   Developer Notes:
1458   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1459   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1460 
1461 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1462           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1463 @*/
1464 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1465 {
1466   PetscFunctionBeginHot;
1467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1468   PetscValidType(mat, 1);
1469   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1470   PetscValidIntPointer(idxm, 3);
1471   PetscValidIntPointer(idxn, 5);
1472   MatCheckPreallocated(mat, 1);
1473 
1474   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1475   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1476 
1477   if (PetscDefined(USE_DEBUG)) {
1478     PetscInt i, j;
1479 
1480     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1481     for (i = 0; i < m; i++) {
1482       for (j = 0; j < n; j++) {
1483         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1484 #if defined(PETSC_USE_COMPLEX)
1485           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]);
1486 #else
1487           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]);
1488 #endif
1489       }
1490     }
1491     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);
1492     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);
1493   }
1494 
1495   if (mat->assembled) {
1496     mat->was_assembled = PETSC_TRUE;
1497     mat->assembled     = PETSC_FALSE;
1498   }
1499   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1500   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1501   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1502   PetscFunctionReturn(PETSC_SUCCESS);
1503 }
1504 
1505 /*@C
1506   MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1507   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1508   MUST be called after all calls to `MatSetValues()` have been completed.
1509 
1510   Not Collective
1511 
1512   Input Parameters:
1513 + mat  - the matrix
1514 . v    - a logically two-dimensional array of values
1515 . ism  - the rows to provide
1516 . isn  - the columns to provide
1517 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1518 
1519   Level: beginner
1520 
1521   Notes:
1522   By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1523 
1524   Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1525   options cannot be mixed without intervening calls to the assembly
1526   routines.
1527 
1528   `MatSetValues()` uses 0-based row and column numbers in Fortran
1529   as well as in C.
1530 
1531   Negative indices may be passed in `ism` and `isn`, these rows and columns are
1532   simply ignored. This allows easily inserting element stiffness matrices
1533   with homogeneous Dirchlet boundary conditions that you don't want represented
1534   in the matrix.
1535 
1536   Efficiency Alert:
1537   The routine `MatSetValuesBlocked()` may offer much better efficiency
1538   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1539 
1540   This is currently not optimized for any particular `ISType`
1541 
1542   Developer Notes:
1543   This is labeled with C so does not automatically generate Fortran stubs and interfaces
1544   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1545 
1546 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1547           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1548 @*/
1549 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1550 {
1551   PetscInt        m, n;
1552   const PetscInt *rows, *cols;
1553 
1554   PetscFunctionBeginHot;
1555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1556   PetscCall(ISGetIndices(ism, &rows));
1557   PetscCall(ISGetIndices(isn, &cols));
1558   PetscCall(ISGetLocalSize(ism, &m));
1559   PetscCall(ISGetLocalSize(isn, &n));
1560   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1561   PetscCall(ISRestoreIndices(ism, &rows));
1562   PetscCall(ISRestoreIndices(isn, &cols));
1563   PetscFunctionReturn(PETSC_SUCCESS);
1564 }
1565 
1566 /*@
1567   MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1568   values into a matrix
1569 
1570   Not Collective
1571 
1572   Input Parameters:
1573 + mat - the matrix
1574 . row - the (block) row to set
1575 - v   - a logically two-dimensional array of values
1576 
1577   Level: intermediate
1578 
1579   Notes:
1580   The values, `v`, are column-oriented (for the block version) and sorted
1581 
1582   All the nonzeros in the row must be provided
1583 
1584   The matrix must have previously had its column indices set, likely by having been assembled.
1585 
1586   The row must belong to this process
1587 
1588 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1589           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1590 @*/
1591 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1592 {
1593   PetscInt globalrow;
1594 
1595   PetscFunctionBegin;
1596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1597   PetscValidType(mat, 1);
1598   PetscValidScalarPointer(v, 3);
1599   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1600   PetscCall(MatSetValuesRow(mat, globalrow, v));
1601   PetscFunctionReturn(PETSC_SUCCESS);
1602 }
1603 
1604 /*@
1605   MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1606   values into a matrix
1607 
1608   Not Collective
1609 
1610   Input Parameters:
1611 + mat - the matrix
1612 . row - the (block) row to set
1613 - v   - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1614 
1615   Level: advanced
1616 
1617   Notes:
1618   The values, `v`, are column-oriented for the block version.
1619 
1620   All the nonzeros in the row must be provided
1621 
1622   THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1623 
1624   The row must belong to this process
1625 
1626 .seealso: [](ch_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1627           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1628 @*/
1629 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1630 {
1631   PetscFunctionBeginHot;
1632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1633   PetscValidType(mat, 1);
1634   MatCheckPreallocated(mat, 1);
1635   PetscValidScalarPointer(v, 3);
1636   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1637   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1638   mat->insertmode = INSERT_VALUES;
1639 
1640   if (mat->assembled) {
1641     mat->was_assembled = PETSC_TRUE;
1642     mat->assembled     = PETSC_FALSE;
1643   }
1644   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1645   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1646   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1647   PetscFunctionReturn(PETSC_SUCCESS);
1648 }
1649 
1650 /*@
1651   MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1652   Using structured grid indexing
1653 
1654   Not Collective
1655 
1656   Input Parameters:
1657 + mat  - the matrix
1658 . m    - number of rows being entered
1659 . idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1660 . n    - number of columns being entered
1661 . idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1662 . v    - a logically two-dimensional array of values
1663 - addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1664 
1665   Level: beginner
1666 
1667   Notes:
1668   By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1669 
1670   Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1671   options cannot be mixed without intervening calls to the assembly
1672   routines.
1673 
1674   The grid coordinates are across the entire grid, not just the local portion
1675 
1676   `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1677   as well as in C.
1678 
1679   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1680 
1681   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1682   or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1683 
1684   The columns and rows in the stencil passed in MUST be contained within the
1685   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1686   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1687   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1688   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1689 
1690   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1691   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1692   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1693   `DM_BOUNDARY_PERIODIC` boundary type.
1694 
1695   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
1696   a single value per point) you can skip filling those indices.
1697 
1698   Inspired by the structured grid interface to the HYPRE package
1699   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1700 
1701   Efficiency Alert:
1702   The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1703   for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1704 
1705   Fortran Notes:
1706   `idxm` and `idxn` should be declared as
1707 $     MatStencil idxm(4,m),idxn(4,n)
1708   and the values inserted using
1709 .vb
1710     idxm(MatStencil_i,1) = i
1711     idxm(MatStencil_j,1) = j
1712     idxm(MatStencil_k,1) = k
1713     idxm(MatStencil_c,1) = c
1714     etc
1715 .ve
1716 
1717 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1718           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1719 @*/
1720 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1721 {
1722   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1723   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1724   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1725 
1726   PetscFunctionBegin;
1727   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1728   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1729   PetscValidType(mat, 1);
1730   PetscValidPointer(idxm, 3);
1731   PetscValidPointer(idxn, 5);
1732 
1733   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1734     jdxm = buf;
1735     jdxn = buf + m;
1736   } else {
1737     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1738     jdxm = bufm;
1739     jdxn = bufn;
1740   }
1741   for (i = 0; i < m; i++) {
1742     for (j = 0; j < 3 - sdim; j++) dxm++;
1743     tmp = *dxm++ - starts[0];
1744     for (j = 0; j < dim - 1; j++) {
1745       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1746       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1747     }
1748     if (mat->stencil.noc) dxm++;
1749     jdxm[i] = tmp;
1750   }
1751   for (i = 0; i < n; i++) {
1752     for (j = 0; j < 3 - sdim; j++) dxn++;
1753     tmp = *dxn++ - starts[0];
1754     for (j = 0; j < dim - 1; j++) {
1755       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1756       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1757     }
1758     if (mat->stencil.noc) dxn++;
1759     jdxn[i] = tmp;
1760   }
1761   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1762   PetscCall(PetscFree2(bufm, bufn));
1763   PetscFunctionReturn(PETSC_SUCCESS);
1764 }
1765 
1766 /*@
1767   MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1768   Using structured grid indexing
1769 
1770   Not Collective
1771 
1772   Input Parameters:
1773 + mat  - the matrix
1774 . m    - number of rows being entered
1775 . idxm - grid coordinates for matrix rows being entered
1776 . n    - number of columns being entered
1777 . idxn - grid coordinates for matrix columns being entered
1778 . v    - a logically two-dimensional array of values
1779 - addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1780 
1781   Level: beginner
1782 
1783   Notes:
1784   By default the values, `v`, are row-oriented and unsorted.
1785   See `MatSetOption()` for other options.
1786 
1787   Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1788   options cannot be mixed without intervening calls to the assembly
1789   routines.
1790 
1791   The grid coordinates are across the entire grid, not just the local portion
1792 
1793   `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1794   as well as in C.
1795 
1796   For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1797 
1798   In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1799   or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1800 
1801   The columns and rows in the stencil passed in MUST be contained within the
1802   ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1803   if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1804   local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1805   first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1806 
1807   Negative indices may be passed in idxm and idxn, these rows and columns are
1808   simply ignored. This allows easily inserting element stiffness matrices
1809   with homogeneous Dirchlet boundary conditions that you don't want represented
1810   in the matrix.
1811 
1812   Inspired by the structured grid interface to the HYPRE package
1813   (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1814 
1815   Fortran Notes:
1816   `idxm` and `idxn` should be declared as
1817 $     MatStencil idxm(4,m),idxn(4,n)
1818   and the values inserted using
1819 .vb
1820     idxm(MatStencil_i,1) = i
1821     idxm(MatStencil_j,1) = j
1822     idxm(MatStencil_k,1) = k
1823    etc
1824 .ve
1825 
1826 .seealso: [](ch_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1827           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1828           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1829 @*/
1830 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1831 {
1832   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1833   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1834   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1835 
1836   PetscFunctionBegin;
1837   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1838   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1839   PetscValidType(mat, 1);
1840   PetscValidPointer(idxm, 3);
1841   PetscValidPointer(idxn, 5);
1842   PetscValidScalarPointer(v, 6);
1843 
1844   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1845     jdxm = buf;
1846     jdxn = buf + m;
1847   } else {
1848     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1849     jdxm = bufm;
1850     jdxn = bufn;
1851   }
1852   for (i = 0; i < m; i++) {
1853     for (j = 0; j < 3 - sdim; j++) dxm++;
1854     tmp = *dxm++ - starts[0];
1855     for (j = 0; j < sdim - 1; j++) {
1856       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1857       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1858     }
1859     dxm++;
1860     jdxm[i] = tmp;
1861   }
1862   for (i = 0; i < n; i++) {
1863     for (j = 0; j < 3 - sdim; j++) dxn++;
1864     tmp = *dxn++ - starts[0];
1865     for (j = 0; j < sdim - 1; j++) {
1866       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1867       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1868     }
1869     dxn++;
1870     jdxn[i] = tmp;
1871   }
1872   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1873   PetscCall(PetscFree2(bufm, bufn));
1874   PetscFunctionReturn(PETSC_SUCCESS);
1875 }
1876 
1877 /*@
1878   MatSetStencil - Sets the grid information for setting values into a matrix via
1879   `MatSetValuesStencil()`
1880 
1881   Not Collective
1882 
1883   Input Parameters:
1884 + mat    - the matrix
1885 . dim    - dimension of the grid 1, 2, or 3
1886 . dims   - number of grid points in x, y, and z direction, including ghost points on your processor
1887 . starts - starting point of ghost nodes on your processor in x, y, and z direction
1888 - dof    - number of degrees of freedom per node
1889 
1890   Level: beginner
1891 
1892   Notes:
1893   Inspired by the structured grid interface to the HYPRE package
1894   (www.llnl.gov/CASC/hyper)
1895 
1896   For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1897   user.
1898 
1899 .seealso: [](ch_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1900           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1901 @*/
1902 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1903 {
1904   PetscFunctionBegin;
1905   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1906   PetscValidIntPointer(dims, 3);
1907   PetscValidIntPointer(starts, 4);
1908 
1909   mat->stencil.dim = dim + (dof > 1);
1910   for (PetscInt i = 0; i < dim; i++) {
1911     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1912     mat->stencil.starts[i] = starts[dim - i - 1];
1913   }
1914   mat->stencil.dims[dim]   = dof;
1915   mat->stencil.starts[dim] = 0;
1916   mat->stencil.noc         = (PetscBool)(dof == 1);
1917   PetscFunctionReturn(PETSC_SUCCESS);
1918 }
1919 
1920 /*@C
1921   MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1922 
1923   Not Collective
1924 
1925   Input Parameters:
1926 + mat  - the matrix
1927 . v    - a logically two-dimensional array of values
1928 . m    - the number of block rows
1929 . idxm - the global block indices
1930 . n    - the number of block columns
1931 . idxn - the global block indices
1932 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1933 
1934   Level: intermediate
1935 
1936   Notes:
1937   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1938   MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1939 
1940   The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1941   NOT the total number of rows/columns; for example, if the block size is 2 and
1942   you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1943   The values in idxm would be 1 2; that is the first index for each block divided by
1944   the block size.
1945 
1946   You must call `MatSetBlockSize()` when constructing this matrix (before
1947   preallocating it).
1948 
1949   By default the values, `v`, are row-oriented, so the layout of
1950   `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1951 
1952   Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1953   options cannot be mixed without intervening calls to the assembly
1954   routines.
1955 
1956   `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1957   as well as in C.
1958 
1959   Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1960   simply ignored. This allows easily inserting element stiffness matrices
1961   with homogeneous Dirchlet boundary conditions that you don't want represented
1962   in the matrix.
1963 
1964   Each time an entry is set within a sparse matrix via `MatSetValues()`,
1965   internal searching must be done to determine where to place the
1966   data in the matrix storage space.  By instead inserting blocks of
1967   entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1968   reduced.
1969 
1970   Example:
1971 .vb
1972    Suppose m=n=2 and block size(bs) = 2 The array is
1973 
1974    1  2  | 3  4
1975    5  6  | 7  8
1976    - - - | - - -
1977    9  10 | 11 12
1978    13 14 | 15 16
1979 
1980    v[] should be passed in like
1981    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1982 
1983   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1984    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1985 .ve
1986 
1987 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1988 @*/
1989 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1990 {
1991   PetscFunctionBeginHot;
1992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1993   PetscValidType(mat, 1);
1994   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1995   PetscValidIntPointer(idxm, 3);
1996   PetscValidIntPointer(idxn, 5);
1997   MatCheckPreallocated(mat, 1);
1998   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1999   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2000   if (PetscDefined(USE_DEBUG)) {
2001     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2002     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2003   }
2004   if (PetscDefined(USE_DEBUG)) {
2005     PetscInt rbs, cbs, M, N, i;
2006     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
2007     PetscCall(MatGetSize(mat, &M, &N));
2008     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);
2009     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);
2010   }
2011   if (mat->assembled) {
2012     mat->was_assembled = PETSC_TRUE;
2013     mat->assembled     = PETSC_FALSE;
2014   }
2015   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2016   if (mat->ops->setvaluesblocked) {
2017     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
2018   } else {
2019     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
2020     PetscInt i, j, bs, cbs;
2021 
2022     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2023     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2024       iidxm = buf;
2025       iidxn = buf + m * bs;
2026     } else {
2027       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2028       iidxm = bufr;
2029       iidxn = bufc;
2030     }
2031     for (i = 0; i < m; i++) {
2032       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2033     }
2034     if (m != n || bs != cbs || idxm != idxn) {
2035       for (i = 0; i < n; i++) {
2036         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2037       }
2038     } else iidxn = iidxm;
2039     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2040     PetscCall(PetscFree2(bufr, bufc));
2041   }
2042   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2043   PetscFunctionReturn(PETSC_SUCCESS);
2044 }
2045 
2046 /*@C
2047   MatGetValues - Gets a block of local values from a matrix.
2048 
2049   Not Collective; can only return values that are owned by the give process
2050 
2051   Input Parameters:
2052 + mat  - the matrix
2053 . v    - a logically two-dimensional array for storing the values
2054 . m    - the number of rows
2055 . idxm - the  global indices of the rows
2056 . n    - the number of columns
2057 - idxn - the global indices of the columns
2058 
2059   Level: advanced
2060 
2061   Notes:
2062   The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2063   The values, `v`, are then returned in a row-oriented format,
2064   analogous to that used by default in `MatSetValues()`.
2065 
2066   `MatGetValues()` uses 0-based row and column numbers in
2067   Fortran as well as in C.
2068 
2069   `MatGetValues()` requires that the matrix has been assembled
2070   with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2071   `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2072   without intermediate matrix assembly.
2073 
2074   Negative row or column indices will be ignored and those locations in `v` will be
2075   left unchanged.
2076 
2077   For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI process.
2078   That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2079   from `MatGetOwnershipRange`(mat,&rstart,&rend).
2080 
2081 .seealso: [](ch_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2082 @*/
2083 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2084 {
2085   PetscFunctionBegin;
2086   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2087   PetscValidType(mat, 1);
2088   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2089   PetscValidIntPointer(idxm, 3);
2090   PetscValidIntPointer(idxn, 5);
2091   PetscValidScalarPointer(v, 6);
2092   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2093   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2094   MatCheckPreallocated(mat, 1);
2095 
2096   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2097   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2098   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2099   PetscFunctionReturn(PETSC_SUCCESS);
2100 }
2101 
2102 /*@C
2103   MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2104   defined previously by `MatSetLocalToGlobalMapping()`
2105 
2106   Not Collective
2107 
2108   Input Parameters:
2109 + mat  - the matrix
2110 . nrow - number of rows
2111 . irow - the row local indices
2112 . ncol - number of columns
2113 - icol - the column local indices
2114 
2115   Output Parameter:
2116 . y - a logically two-dimensional array of values
2117 
2118   Level: advanced
2119 
2120   Notes:
2121   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2122 
2123   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,
2124   are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2125   determine if the resulting global row associated with the local row r is owned by the requesting MPI process by applying the `ISLocalToGlobalMapping` set
2126   with `MatSetLocalToGlobalMapping()`.
2127 
2128   Developer Notes:
2129   This is labelled with C so does not automatically generate Fortran stubs and interfaces
2130   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2131 
2132 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2133           `MatSetValuesLocal()`, `MatGetValues()`
2134 @*/
2135 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2136 {
2137   PetscFunctionBeginHot;
2138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2139   PetscValidType(mat, 1);
2140   MatCheckPreallocated(mat, 1);
2141   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2142   PetscValidIntPointer(irow, 3);
2143   PetscValidIntPointer(icol, 5);
2144   if (PetscDefined(USE_DEBUG)) {
2145     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2146     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2147   }
2148   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2149   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2150   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2151   else {
2152     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2153     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2154       irowm = buf;
2155       icolm = buf + nrow;
2156     } else {
2157       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2158       irowm = bufr;
2159       icolm = bufc;
2160     }
2161     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2162     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2163     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2164     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2165     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2166     PetscCall(PetscFree2(bufr, bufc));
2167   }
2168   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2169   PetscFunctionReturn(PETSC_SUCCESS);
2170 }
2171 
2172 /*@
2173   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2174   the same size. Currently, this can only be called once and creates the given matrix.
2175 
2176   Not Collective
2177 
2178   Input Parameters:
2179 + mat  - the matrix
2180 . nb   - the number of blocks
2181 . bs   - the number of rows (and columns) in each block
2182 . rows - a concatenation of the rows for each block
2183 - v    - a concatenation of logically two-dimensional arrays of values
2184 
2185   Level: advanced
2186 
2187   Note:
2188   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2189 
2190   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2191 
2192 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2193           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2194 @*/
2195 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2196 {
2197   PetscFunctionBegin;
2198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2199   PetscValidType(mat, 1);
2200   PetscValidIntPointer(rows, 4);
2201   PetscValidScalarPointer(v, 5);
2202   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2203 
2204   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2205   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2206   else {
2207     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2208   }
2209   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2210   PetscFunctionReturn(PETSC_SUCCESS);
2211 }
2212 
2213 /*@
2214   MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2215   the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2216   using a local (per-processor) numbering.
2217 
2218   Not Collective
2219 
2220   Input Parameters:
2221 + x        - the matrix
2222 . rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2223 - cmapping - column mapping
2224 
2225   Level: intermediate
2226 
2227   Note:
2228   If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2229 
2230 .seealso: [](ch_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2231 @*/
2232 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2233 {
2234   PetscFunctionBegin;
2235   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2236   PetscValidType(x, 1);
2237   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2238   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2239   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2240   else {
2241     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2242     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2243   }
2244   PetscFunctionReturn(PETSC_SUCCESS);
2245 }
2246 
2247 /*@
2248   MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2249 
2250   Not Collective
2251 
2252   Input Parameter:
2253 . A - the matrix
2254 
2255   Output Parameters:
2256 + rmapping - row mapping
2257 - cmapping - column mapping
2258 
2259   Level: advanced
2260 
2261 .seealso: [](ch_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2262 @*/
2263 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2264 {
2265   PetscFunctionBegin;
2266   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2267   PetscValidType(A, 1);
2268   if (rmapping) {
2269     PetscValidPointer(rmapping, 2);
2270     *rmapping = A->rmap->mapping;
2271   }
2272   if (cmapping) {
2273     PetscValidPointer(cmapping, 3);
2274     *cmapping = A->cmap->mapping;
2275   }
2276   PetscFunctionReturn(PETSC_SUCCESS);
2277 }
2278 
2279 /*@
2280   MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2281 
2282   Logically Collective
2283 
2284   Input Parameters:
2285 + A    - the matrix
2286 . rmap - row layout
2287 - cmap - column layout
2288 
2289   Level: advanced
2290 
2291   Note:
2292   The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2293 
2294 .seealso: [](ch_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2295 @*/
2296 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2297 {
2298   PetscFunctionBegin;
2299   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2300   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2301   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2302   PetscFunctionReturn(PETSC_SUCCESS);
2303 }
2304 
2305 /*@
2306   MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2307 
2308   Not Collective
2309 
2310   Input Parameter:
2311 . A - the matrix
2312 
2313   Output Parameters:
2314 + rmap - row layout
2315 - cmap - column layout
2316 
2317   Level: advanced
2318 
2319 .seealso: [](ch_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2320 @*/
2321 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2322 {
2323   PetscFunctionBegin;
2324   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2325   PetscValidType(A, 1);
2326   if (rmap) {
2327     PetscValidPointer(rmap, 2);
2328     *rmap = A->rmap;
2329   }
2330   if (cmap) {
2331     PetscValidPointer(cmap, 3);
2332     *cmap = A->cmap;
2333   }
2334   PetscFunctionReturn(PETSC_SUCCESS);
2335 }
2336 
2337 /*@C
2338   MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2339   using a local numbering of the nodes.
2340 
2341   Not Collective
2342 
2343   Input Parameters:
2344 + mat  - the matrix
2345 . nrow - number of rows
2346 . irow - the row local indices
2347 . ncol - number of columns
2348 . icol - the column local indices
2349 . y    - a logically two-dimensional array of values
2350 - addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2351 
2352   Level: intermediate
2353 
2354   Notes:
2355   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2356   `MatSetUp()` before using this routine
2357 
2358   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2359 
2360   Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2361   options cannot be mixed without intervening calls to the assembly
2362   routines.
2363 
2364   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2365   MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2366 
2367   Developer Notes:
2368   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2369   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2370 
2371 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2372           `MatGetValuesLocal()`
2373 @*/
2374 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2375 {
2376   PetscFunctionBeginHot;
2377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2378   PetscValidType(mat, 1);
2379   MatCheckPreallocated(mat, 1);
2380   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2381   PetscValidIntPointer(irow, 3);
2382   PetscValidIntPointer(icol, 5);
2383   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2384   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2385   if (PetscDefined(USE_DEBUG)) {
2386     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2387     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2388   }
2389 
2390   if (mat->assembled) {
2391     mat->was_assembled = PETSC_TRUE;
2392     mat->assembled     = PETSC_FALSE;
2393   }
2394   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2395   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2396   else {
2397     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2398     const PetscInt *irowm, *icolm;
2399 
2400     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2401       bufr  = buf;
2402       bufc  = buf + nrow;
2403       irowm = bufr;
2404       icolm = bufc;
2405     } else {
2406       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2407       irowm = bufr;
2408       icolm = bufc;
2409     }
2410     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2411     else irowm = irow;
2412     if (mat->cmap->mapping) {
2413       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2414         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2415       } else icolm = irowm;
2416     } else icolm = icol;
2417     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2418     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2419   }
2420   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2421   PetscFunctionReturn(PETSC_SUCCESS);
2422 }
2423 
2424 /*@C
2425   MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2426   using a local ordering of the nodes a block at a time.
2427 
2428   Not Collective
2429 
2430   Input Parameters:
2431 + mat  - the matrix
2432 . nrow - number of rows
2433 . irow - the row local indices
2434 . ncol - number of columns
2435 . icol - the column local indices
2436 . y    - a logically two-dimensional array of values
2437 - addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2438 
2439   Level: intermediate
2440 
2441   Notes:
2442   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2443   `MatSetUp()` before using this routine
2444 
2445   If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2446   before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2447 
2448   Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2449   options cannot be mixed without intervening calls to the assembly
2450   routines.
2451 
2452   These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2453   MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2454 
2455   Developer Notes:
2456   This is labeled with C so does not automatically generate Fortran stubs and interfaces
2457   because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2458 
2459 .seealso: [](ch_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2460           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2461 @*/
2462 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2463 {
2464   PetscFunctionBeginHot;
2465   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2466   PetscValidType(mat, 1);
2467   MatCheckPreallocated(mat, 1);
2468   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2469   PetscValidIntPointer(irow, 3);
2470   PetscValidIntPointer(icol, 5);
2471   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2472   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2473   if (PetscDefined(USE_DEBUG)) {
2474     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2475     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);
2476   }
2477 
2478   if (mat->assembled) {
2479     mat->was_assembled = PETSC_TRUE;
2480     mat->assembled     = PETSC_FALSE;
2481   }
2482   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2483     PetscInt irbs, rbs;
2484     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2485     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2486     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2487   }
2488   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2489     PetscInt icbs, cbs;
2490     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2491     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2492     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2493   }
2494   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2495   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2496   else {
2497     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2498     const PetscInt *irowm, *icolm;
2499 
2500     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2501       bufr  = buf;
2502       bufc  = buf + nrow;
2503       irowm = bufr;
2504       icolm = bufc;
2505     } else {
2506       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2507       irowm = bufr;
2508       icolm = bufc;
2509     }
2510     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2511     else irowm = irow;
2512     if (mat->cmap->mapping) {
2513       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2514         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2515       } else icolm = irowm;
2516     } else icolm = icol;
2517     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2518     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2519   }
2520   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2521   PetscFunctionReturn(PETSC_SUCCESS);
2522 }
2523 
2524 /*@
2525   MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2526 
2527   Collective
2528 
2529   Input Parameters:
2530 + mat - the matrix
2531 - x   - the vector to be multiplied
2532 
2533   Output Parameter:
2534 . y - the result
2535 
2536   Level: developer
2537 
2538   Note:
2539   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2540   call `MatMultDiagonalBlock`(A,y,y).
2541 
2542 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2543 @*/
2544 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2545 {
2546   PetscFunctionBegin;
2547   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2548   PetscValidType(mat, 1);
2549   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2550   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2551 
2552   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2553   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2554   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2555   MatCheckPreallocated(mat, 1);
2556 
2557   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2558   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2559   PetscFunctionReturn(PETSC_SUCCESS);
2560 }
2561 
2562 /*@
2563   MatMult - Computes the matrix-vector product, y = Ax.
2564 
2565   Neighbor-wise Collective
2566 
2567   Input Parameters:
2568 + mat - the matrix
2569 - x   - the vector to be multiplied
2570 
2571   Output Parameter:
2572 . y - the result
2573 
2574   Level: beginner
2575 
2576   Note:
2577   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2578   call `MatMult`(A,y,y).
2579 
2580 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2581 @*/
2582 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2583 {
2584   PetscFunctionBegin;
2585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2586   PetscValidType(mat, 1);
2587   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2588   VecCheckAssembled(x);
2589   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2590   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2591   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2592   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2593   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);
2594   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);
2595   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);
2596   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);
2597   PetscCall(VecSetErrorIfLocked(y, 3));
2598   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2599   MatCheckPreallocated(mat, 1);
2600 
2601   PetscCall(VecLockReadPush(x));
2602   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2603   PetscUseTypeMethod(mat, mult, x, y);
2604   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2605   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2606   PetscCall(VecLockReadPop(x));
2607   PetscFunctionReturn(PETSC_SUCCESS);
2608 }
2609 
2610 /*@
2611   MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2612 
2613   Neighbor-wise Collective
2614 
2615   Input Parameters:
2616 + mat - the matrix
2617 - x   - the vector to be multiplied
2618 
2619   Output Parameter:
2620 . y - the result
2621 
2622   Level: beginner
2623 
2624   Notes:
2625   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2626   call `MatMultTranspose`(A,y,y).
2627 
2628   For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2629   use `MatMultHermitianTranspose()`
2630 
2631 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2632 @*/
2633 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2634 {
2635   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2636 
2637   PetscFunctionBegin;
2638   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2639   PetscValidType(mat, 1);
2640   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2641   VecCheckAssembled(x);
2642   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2643 
2644   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2645   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2646   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2647   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);
2648   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);
2649   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);
2650   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);
2651   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2652   MatCheckPreallocated(mat, 1);
2653 
2654   if (!mat->ops->multtranspose) {
2655     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2656     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);
2657   } else op = mat->ops->multtranspose;
2658   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2659   PetscCall(VecLockReadPush(x));
2660   PetscCall((*op)(mat, x, y));
2661   PetscCall(VecLockReadPop(x));
2662   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2663   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2664   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2665   PetscFunctionReturn(PETSC_SUCCESS);
2666 }
2667 
2668 /*@
2669   MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2670 
2671   Neighbor-wise Collective
2672 
2673   Input Parameters:
2674 + mat - the matrix
2675 - x   - the vector to be multiplied
2676 
2677   Output Parameter:
2678 . y - the result
2679 
2680   Level: beginner
2681 
2682   Notes:
2683   The vectors `x` and `y` cannot be the same.  I.e., one cannot
2684   call `MatMultHermitianTranspose`(A,y,y).
2685 
2686   Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2687 
2688   For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2689 
2690 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2691 @*/
2692 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2693 {
2694   PetscFunctionBegin;
2695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2696   PetscValidType(mat, 1);
2697   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2698   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2699 
2700   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2701   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2702   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2703   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2704   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2705   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2706   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2707   MatCheckPreallocated(mat, 1);
2708 
2709   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2710 #if defined(PETSC_USE_COMPLEX)
2711   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2712     PetscCall(VecLockReadPush(x));
2713     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2714     else PetscUseTypeMethod(mat, mult, x, y);
2715     PetscCall(VecLockReadPop(x));
2716   } else {
2717     Vec w;
2718     PetscCall(VecDuplicate(x, &w));
2719     PetscCall(VecCopy(x, w));
2720     PetscCall(VecConjugate(w));
2721     PetscCall(MatMultTranspose(mat, w, y));
2722     PetscCall(VecDestroy(&w));
2723     PetscCall(VecConjugate(y));
2724   }
2725   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2726 #else
2727   PetscCall(MatMultTranspose(mat, x, y));
2728 #endif
2729   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2730   PetscFunctionReturn(PETSC_SUCCESS);
2731 }
2732 
2733 /*@
2734   MatMultAdd -  Computes v3 = v2 + A * v1.
2735 
2736   Neighbor-wise Collective
2737 
2738   Input Parameters:
2739 + mat - the matrix
2740 . v1  - the vector to be multiplied by `mat`
2741 - v2  - the vector to be added to the result
2742 
2743   Output Parameter:
2744 . v3 - the result
2745 
2746   Level: beginner
2747 
2748   Note:
2749   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2750   call `MatMultAdd`(A,v1,v2,v1).
2751 
2752 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2753 @*/
2754 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2755 {
2756   PetscFunctionBegin;
2757   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2758   PetscValidType(mat, 1);
2759   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2760   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2761   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2762 
2763   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2764   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2765   PetscCheck(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);
2766   /* 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);
2767      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); */
2768   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);
2769   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);
2770   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2771   MatCheckPreallocated(mat, 1);
2772 
2773   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2774   PetscCall(VecLockReadPush(v1));
2775   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2776   PetscCall(VecLockReadPop(v1));
2777   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2778   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2779   PetscFunctionReturn(PETSC_SUCCESS);
2780 }
2781 
2782 /*@
2783   MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2784 
2785   Neighbor-wise Collective
2786 
2787   Input Parameters:
2788 + mat - the matrix
2789 . v1  - the vector to be multiplied by the transpose of the matrix
2790 - v2  - the vector to be added to the result
2791 
2792   Output Parameter:
2793 . v3 - the result
2794 
2795   Level: beginner
2796 
2797   Note:
2798   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2799   call `MatMultTransposeAdd`(A,v1,v2,v1).
2800 
2801 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2802 @*/
2803 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2804 {
2805   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2806 
2807   PetscFunctionBegin;
2808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2809   PetscValidType(mat, 1);
2810   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2811   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2812   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2813 
2814   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2815   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2816   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);
2817   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);
2818   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);
2819   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2820   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2821   MatCheckPreallocated(mat, 1);
2822 
2823   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2824   PetscCall(VecLockReadPush(v1));
2825   PetscCall((*op)(mat, v1, v2, v3));
2826   PetscCall(VecLockReadPop(v1));
2827   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2828   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2829   PetscFunctionReturn(PETSC_SUCCESS);
2830 }
2831 
2832 /*@
2833   MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2834 
2835   Neighbor-wise Collective
2836 
2837   Input Parameters:
2838 + mat - the matrix
2839 . v1  - the vector to be multiplied by the Hermitian transpose
2840 - v2  - the vector to be added to the result
2841 
2842   Output Parameter:
2843 . v3 - the result
2844 
2845   Level: beginner
2846 
2847   Note:
2848   The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2849   call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2850 
2851 .seealso: [](ch_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2852 @*/
2853 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2854 {
2855   PetscFunctionBegin;
2856   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2857   PetscValidType(mat, 1);
2858   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2859   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2860   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2861 
2862   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2863   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2864   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2865   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);
2866   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);
2867   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);
2868   MatCheckPreallocated(mat, 1);
2869 
2870   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2871   PetscCall(VecLockReadPush(v1));
2872   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2873   else {
2874     Vec w, z;
2875     PetscCall(VecDuplicate(v1, &w));
2876     PetscCall(VecCopy(v1, w));
2877     PetscCall(VecConjugate(w));
2878     PetscCall(VecDuplicate(v3, &z));
2879     PetscCall(MatMultTranspose(mat, w, z));
2880     PetscCall(VecDestroy(&w));
2881     PetscCall(VecConjugate(z));
2882     if (v2 != v3) {
2883       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2884     } else {
2885       PetscCall(VecAXPY(v3, 1.0, z));
2886     }
2887     PetscCall(VecDestroy(&z));
2888   }
2889   PetscCall(VecLockReadPop(v1));
2890   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2891   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2892   PetscFunctionReturn(PETSC_SUCCESS);
2893 }
2894 
2895 /*@C
2896   MatGetFactorType - gets the type of factorization it is
2897 
2898   Not Collective
2899 
2900   Input Parameter:
2901 . mat - the matrix
2902 
2903   Output Parameter:
2904 . 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`
2905 
2906   Level: intermediate
2907 
2908 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2909           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2910 @*/
2911 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2912 {
2913   PetscFunctionBegin;
2914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2915   PetscValidType(mat, 1);
2916   PetscValidPointer(t, 2);
2917   *t = mat->factortype;
2918   PetscFunctionReturn(PETSC_SUCCESS);
2919 }
2920 
2921 /*@C
2922   MatSetFactorType - sets the type of factorization it is
2923 
2924   Logically Collective
2925 
2926   Input Parameters:
2927 + mat - the matrix
2928 - 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`
2929 
2930   Level: intermediate
2931 
2932 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2933           `MAT_FACTOR_ICC`,`MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2934 @*/
2935 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2936 {
2937   PetscFunctionBegin;
2938   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2939   PetscValidType(mat, 1);
2940   mat->factortype = t;
2941   PetscFunctionReturn(PETSC_SUCCESS);
2942 }
2943 
2944 /*@C
2945   MatGetInfo - Returns information about matrix storage (number of
2946   nonzeros, memory, etc.).
2947 
2948   Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2949 
2950   Input Parameters:
2951 + mat  - the matrix
2952 - 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)
2953 
2954   Output Parameter:
2955 . info - matrix information context
2956 
2957   Options Database Key:
2958 . -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2959 
2960   Notes:
2961   The `MatInfo` context contains a variety of matrix data, including
2962   number of nonzeros allocated and used, number of mallocs during
2963   matrix assembly, etc.  Additional information for factored matrices
2964   is provided (such as the fill ratio, number of mallocs during
2965   factorization, etc.).
2966 
2967   Example:
2968   See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2969   data within the MatInfo context.  For example,
2970 .vb
2971       MatInfo info;
2972       Mat     A;
2973       double  mal, nz_a, nz_u;
2974 
2975       MatGetInfo(A, MAT_LOCAL, &info);
2976       mal  = info.mallocs;
2977       nz_a = info.nz_allocated;
2978 .ve
2979 
2980   Fortran users should declare info as a double precision
2981   array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2982   of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2983   a complete list of parameter names.
2984 .vb
2985       double  precision info(MAT_INFO_SIZE)
2986       double  precision mal, nz_a
2987       Mat     A
2988       integer ierr
2989 
2990       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2991       mal = info(MAT_INFO_MALLOCS)
2992       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2993 .ve
2994 
2995   Level: intermediate
2996 
2997   Developer Notes:
2998   The Fortran interface is not autogenerated as the
2999   interface definition cannot be generated correctly [due to `MatInfo` argument]
3000 
3001 .seealso: [](ch_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
3002 @*/
3003 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
3004 {
3005   PetscFunctionBegin;
3006   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3007   PetscValidType(mat, 1);
3008   PetscValidPointer(info, 3);
3009   MatCheckPreallocated(mat, 1);
3010   PetscUseTypeMethod(mat, getinfo, flag, info);
3011   PetscFunctionReturn(PETSC_SUCCESS);
3012 }
3013 
3014 /*
3015    This is used by external packages where it is not easy to get the info from the actual
3016    matrix factorization.
3017 */
3018 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
3019 {
3020   PetscFunctionBegin;
3021   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
3022   PetscFunctionReturn(PETSC_SUCCESS);
3023 }
3024 
3025 /*@C
3026   MatLUFactor - Performs in-place LU factorization of matrix.
3027 
3028   Collective
3029 
3030   Input Parameters:
3031 + mat  - the matrix
3032 . row  - row permutation
3033 . col  - column permutation
3034 - info - options for factorization, includes
3035 .vb
3036           fill - expected fill as ratio of original fill.
3037           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3038                    Run with the option -info to determine an optimal value to use
3039 .ve
3040 
3041   Level: developer
3042 
3043   Notes:
3044   Most users should employ the `KSP` interface for linear solvers
3045   instead of working directly with matrix algebra routines such as this.
3046   See, e.g., `KSPCreate()`.
3047 
3048   This changes the state of the matrix to a factored matrix; it cannot be used
3049   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3050 
3051   This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3052   when not using `KSP`.
3053 
3054   Developer Notes:
3055   The Fortran interface is not autogenerated as the
3056   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3057 
3058 .seealso: [](ch_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3059           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3060 @*/
3061 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3062 {
3063   MatFactorInfo tinfo;
3064 
3065   PetscFunctionBegin;
3066   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3067   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3068   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3069   if (info) PetscValidPointer(info, 4);
3070   PetscValidType(mat, 1);
3071   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3072   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3073   MatCheckPreallocated(mat, 1);
3074   if (!info) {
3075     PetscCall(MatFactorInfoInitialize(&tinfo));
3076     info = &tinfo;
3077   }
3078 
3079   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3080   PetscUseTypeMethod(mat, lufactor, row, col, info);
3081   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3082   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3083   PetscFunctionReturn(PETSC_SUCCESS);
3084 }
3085 
3086 /*@C
3087   MatILUFactor - Performs in-place ILU factorization of matrix.
3088 
3089   Collective
3090 
3091   Input Parameters:
3092 + mat  - the matrix
3093 . row  - row permutation
3094 . col  - column permutation
3095 - info - structure containing
3096 .vb
3097       levels - number of levels of fill.
3098       expected fill - as ratio of original fill.
3099       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3100                 missing diagonal entries)
3101 .ve
3102 
3103   Level: developer
3104 
3105   Notes:
3106   Most users should employ the `KSP` interface for linear solvers
3107   instead of working directly with matrix algebra routines such as this.
3108   See, e.g., `KSPCreate()`.
3109 
3110   Probably really in-place only when level of fill is zero, otherwise allocates
3111   new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3112   when not using `KSP`.
3113 
3114   Developer Notes:
3115   The Fortran interface is not autogenerated as the
3116   interface definition cannot be generated correctly [due to MatFactorInfo]
3117 
3118 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3119 @*/
3120 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3121 {
3122   PetscFunctionBegin;
3123   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3124   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3125   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3126   PetscValidPointer(info, 4);
3127   PetscValidType(mat, 1);
3128   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3129   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3130   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3131   MatCheckPreallocated(mat, 1);
3132 
3133   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3134   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3135   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3136   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3137   PetscFunctionReturn(PETSC_SUCCESS);
3138 }
3139 
3140 /*@C
3141   MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3142   Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3143 
3144   Collective
3145 
3146   Input Parameters:
3147 + fact - the factor matrix obtained with `MatGetFactor()`
3148 . mat  - the matrix
3149 . row  - the row permutation
3150 . col  - the column permutation
3151 - info - options for factorization, includes
3152 .vb
3153           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3154           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3155 .ve
3156 
3157   Level: developer
3158 
3159   Notes:
3160   See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3161 
3162   Most users should employ the simplified `KSP` interface for linear solvers
3163   instead of working directly with matrix algebra routines such as this.
3164   See, e.g., `KSPCreate()`.
3165 
3166   Developer Notes:
3167   The Fortran interface is not autogenerated as the
3168   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3169 
3170 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3171 @*/
3172 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3173 {
3174   MatFactorInfo tinfo;
3175 
3176   PetscFunctionBegin;
3177   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3178   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3179   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3180   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3181   if (info) PetscValidPointer(info, 5);
3182   PetscValidType(fact, 1);
3183   PetscValidType(mat, 2);
3184   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3185   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3186   MatCheckPreallocated(mat, 2);
3187   if (!info) {
3188     PetscCall(MatFactorInfoInitialize(&tinfo));
3189     info = &tinfo;
3190   }
3191 
3192   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3193   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3194   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3195   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3196   PetscFunctionReturn(PETSC_SUCCESS);
3197 }
3198 
3199 /*@C
3200   MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3201   Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3202 
3203   Collective
3204 
3205   Input Parameters:
3206 + fact - the factor matrix obtained with `MatGetFactor()`
3207 . mat  - the matrix
3208 - info - options for factorization
3209 
3210   Level: developer
3211 
3212   Notes:
3213   See `MatLUFactor()` for in-place factorization.  See
3214   `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3215 
3216   Most users should employ the `KSP` interface for linear solvers
3217   instead of working directly with matrix algebra routines such as this.
3218   See, e.g., `KSPCreate()`.
3219 
3220   Developer Notes:
3221   The Fortran interface is not autogenerated as the
3222   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3223 
3224 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3225 @*/
3226 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3227 {
3228   MatFactorInfo tinfo;
3229 
3230   PetscFunctionBegin;
3231   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3232   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3233   PetscValidType(fact, 1);
3234   PetscValidType(mat, 2);
3235   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3236   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,
3237              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3238 
3239   MatCheckPreallocated(mat, 2);
3240   if (!info) {
3241     PetscCall(MatFactorInfoInitialize(&tinfo));
3242     info = &tinfo;
3243   }
3244 
3245   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3246   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3247   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3248   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3249   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3250   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3251   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3252   PetscFunctionReturn(PETSC_SUCCESS);
3253 }
3254 
3255 /*@C
3256   MatCholeskyFactor - Performs in-place Cholesky factorization of a
3257   symmetric matrix.
3258 
3259   Collective
3260 
3261   Input Parameters:
3262 + mat  - the matrix
3263 . perm - row and column permutations
3264 - info - expected fill as ratio of original fill
3265 
3266   Level: developer
3267 
3268   Notes:
3269   See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3270   `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3271 
3272   Most users should employ the `KSP` interface for linear solvers
3273   instead of working directly with matrix algebra routines such as this.
3274   See, e.g., `KSPCreate()`.
3275 
3276   Developer Notes:
3277   The Fortran interface is not autogenerated as the
3278   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3279 
3280 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3281           `MatGetOrdering()`
3282 @*/
3283 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3284 {
3285   MatFactorInfo tinfo;
3286 
3287   PetscFunctionBegin;
3288   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3289   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3290   if (info) PetscValidPointer(info, 3);
3291   PetscValidType(mat, 1);
3292   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3293   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3294   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3295   MatCheckPreallocated(mat, 1);
3296   if (!info) {
3297     PetscCall(MatFactorInfoInitialize(&tinfo));
3298     info = &tinfo;
3299   }
3300 
3301   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3302   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3303   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3304   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3305   PetscFunctionReturn(PETSC_SUCCESS);
3306 }
3307 
3308 /*@C
3309   MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3310   of a symmetric matrix.
3311 
3312   Collective
3313 
3314   Input Parameters:
3315 + fact - the factor matrix obtained with `MatGetFactor()`
3316 . mat  - the matrix
3317 . perm - row and column permutations
3318 - info - options for factorization, includes
3319 .vb
3320           fill - expected fill as ratio of original fill.
3321           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3322                    Run with the option -info to determine an optimal value to use
3323 .ve
3324 
3325   Level: developer
3326 
3327   Notes:
3328   See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3329   `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3330 
3331   Most users should employ the `KSP` interface for linear solvers
3332   instead of working directly with matrix algebra routines such as this.
3333   See, e.g., `KSPCreate()`.
3334 
3335   Developer Notes:
3336   The Fortran interface is not autogenerated as the
3337   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3338 
3339 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3340           `MatGetOrdering()`
3341 @*/
3342 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3343 {
3344   MatFactorInfo tinfo;
3345 
3346   PetscFunctionBegin;
3347   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3348   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3349   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3350   if (info) PetscValidPointer(info, 4);
3351   PetscValidType(fact, 1);
3352   PetscValidType(mat, 2);
3353   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3354   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3355   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3356   MatCheckPreallocated(mat, 2);
3357   if (!info) {
3358     PetscCall(MatFactorInfoInitialize(&tinfo));
3359     info = &tinfo;
3360   }
3361 
3362   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3363   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3364   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3365   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3366   PetscFunctionReturn(PETSC_SUCCESS);
3367 }
3368 
3369 /*@C
3370   MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3371   of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3372   `MatCholeskyFactorSymbolic()`.
3373 
3374   Collective
3375 
3376   Input Parameters:
3377 + fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3378 . mat  - the initial matrix that is to be factored
3379 - info - options for factorization
3380 
3381   Level: developer
3382 
3383   Note:
3384   Most users should employ the `KSP` interface for linear solvers
3385   instead of working directly with matrix algebra routines such as this.
3386   See, e.g., `KSPCreate()`.
3387 
3388   Developer Notes:
3389   The Fortran interface is not autogenerated as the
3390   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3391 
3392 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3393 @*/
3394 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3395 {
3396   MatFactorInfo tinfo;
3397 
3398   PetscFunctionBegin;
3399   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3400   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3401   PetscValidType(fact, 1);
3402   PetscValidType(mat, 2);
3403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3404   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,
3405              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3406   MatCheckPreallocated(mat, 2);
3407   if (!info) {
3408     PetscCall(MatFactorInfoInitialize(&tinfo));
3409     info = &tinfo;
3410   }
3411 
3412   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3413   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3414   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3415   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3416   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3417   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3418   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3419   PetscFunctionReturn(PETSC_SUCCESS);
3420 }
3421 
3422 /*@
3423   MatQRFactor - Performs in-place QR factorization of matrix.
3424 
3425   Collective
3426 
3427   Input Parameters:
3428 + mat  - the matrix
3429 . col  - column permutation
3430 - info - options for factorization, includes
3431 .vb
3432           fill - expected fill as ratio of original fill.
3433           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3434                    Run with the option -info to determine an optimal value to use
3435 .ve
3436 
3437   Level: developer
3438 
3439   Notes:
3440   Most users should employ the `KSP` interface for linear solvers
3441   instead of working directly with matrix algebra routines such as this.
3442   See, e.g., `KSPCreate()`.
3443 
3444   This changes the state of the matrix to a factored matrix; it cannot be used
3445   for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3446 
3447   Developer Notes:
3448   The Fortran interface is not autogenerated as the
3449   interface definition cannot be generated correctly [due to MatFactorInfo]
3450 
3451 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3452           `MatSetUnfactored()`
3453 @*/
3454 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3455 {
3456   PetscFunctionBegin;
3457   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3458   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3459   if (info) PetscValidPointer(info, 3);
3460   PetscValidType(mat, 1);
3461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3463   MatCheckPreallocated(mat, 1);
3464   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3465   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3466   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3467   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3468   PetscFunctionReturn(PETSC_SUCCESS);
3469 }
3470 
3471 /*@
3472   MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3473   Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3474 
3475   Collective
3476 
3477   Input Parameters:
3478 + fact - the factor matrix obtained with `MatGetFactor()`
3479 . mat  - the matrix
3480 . col  - column permutation
3481 - info - options for factorization, includes
3482 .vb
3483           fill - expected fill as ratio of original fill.
3484           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3485                    Run with the option -info to determine an optimal value to use
3486 .ve
3487 
3488   Level: developer
3489 
3490   Note:
3491   Most users should employ the `KSP` interface for linear solvers
3492   instead of working directly with matrix algebra routines such as this.
3493   See, e.g., `KSPCreate()`.
3494 
3495   Developer Notes:
3496   The Fortran interface is not autogenerated as the
3497   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3498 
3499 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfoInitialize()`
3500 @*/
3501 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3502 {
3503   MatFactorInfo tinfo;
3504 
3505   PetscFunctionBegin;
3506   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3507   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3508   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3509   if (info) PetscValidPointer(info, 4);
3510   PetscValidType(fact, 1);
3511   PetscValidType(mat, 2);
3512   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3513   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3514   MatCheckPreallocated(mat, 2);
3515   if (!info) {
3516     PetscCall(MatFactorInfoInitialize(&tinfo));
3517     info = &tinfo;
3518   }
3519 
3520   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3521   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3522   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3523   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3524   PetscFunctionReturn(PETSC_SUCCESS);
3525 }
3526 
3527 /*@
3528   MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3529   Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3530 
3531   Collective
3532 
3533   Input Parameters:
3534 + fact - the factor matrix obtained with `MatGetFactor()`
3535 . mat  - the matrix
3536 - info - options for factorization
3537 
3538   Level: developer
3539 
3540   Notes:
3541   See `MatQRFactor()` for in-place factorization.
3542 
3543   Most users should employ the `KSP` interface for linear solvers
3544   instead of working directly with matrix algebra routines such as this.
3545   See, e.g., `KSPCreate()`.
3546 
3547   Developer Notes:
3548   The Fortran interface is not autogenerated as the
3549   interface definition cannot be generated correctly [due to `MatFactorInfo`]
3550 
3551 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3552 @*/
3553 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3554 {
3555   MatFactorInfo tinfo;
3556 
3557   PetscFunctionBegin;
3558   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3559   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3560   PetscValidType(fact, 1);
3561   PetscValidType(mat, 2);
3562   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3563   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,
3564              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3565 
3566   MatCheckPreallocated(mat, 2);
3567   if (!info) {
3568     PetscCall(MatFactorInfoInitialize(&tinfo));
3569     info = &tinfo;
3570   }
3571 
3572   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3573   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3574   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3575   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3576   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3577   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3578   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3579   PetscFunctionReturn(PETSC_SUCCESS);
3580 }
3581 
3582 /*@
3583   MatSolve - Solves A x = b, given a factored matrix.
3584 
3585   Neighbor-wise Collective
3586 
3587   Input Parameters:
3588 + mat - the factored matrix
3589 - b   - the right-hand-side vector
3590 
3591   Output Parameter:
3592 . x - the result vector
3593 
3594   Level: developer
3595 
3596   Notes:
3597   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3598   call `MatSolve`(A,x,x).
3599 
3600   Most users should employ the `KSP` interface for linear solvers
3601   instead of working directly with matrix algebra routines such as this.
3602   See, e.g., `KSPCreate()`.
3603 
3604 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3605 @*/
3606 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3607 {
3608   PetscFunctionBegin;
3609   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3610   PetscValidType(mat, 1);
3611   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3612   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3613   PetscCheckSameComm(mat, 1, b, 2);
3614   PetscCheckSameComm(mat, 1, x, 3);
3615   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3616   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);
3617   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);
3618   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);
3619   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3620   MatCheckPreallocated(mat, 1);
3621 
3622   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3623   if (mat->factorerrortype) {
3624     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3625     PetscCall(VecSetInf(x));
3626   } else PetscUseTypeMethod(mat, solve, b, x);
3627   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3628   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3629   PetscFunctionReturn(PETSC_SUCCESS);
3630 }
3631 
3632 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3633 {
3634   Vec      b, x;
3635   PetscInt N, i;
3636   PetscErrorCode (*f)(Mat, Vec, Vec);
3637   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3638 
3639   PetscFunctionBegin;
3640   if (A->factorerrortype) {
3641     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3642     PetscCall(MatSetInf(X));
3643     PetscFunctionReturn(PETSC_SUCCESS);
3644   }
3645   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3646   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3647   PetscCall(MatBoundToCPU(A, &Abound));
3648   if (!Abound) {
3649     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3650     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3651   }
3652 #if PetscDefined(HAVE_CUDA)
3653   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3654   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3655 #elif PetscDefined(HAVE_HIP)
3656   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3657   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3658 #endif
3659   PetscCall(MatGetSize(B, NULL, &N));
3660   for (i = 0; i < N; i++) {
3661     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3662     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3663     PetscCall((*f)(A, b, x));
3664     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3665     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3666   }
3667   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3668   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3669   PetscFunctionReturn(PETSC_SUCCESS);
3670 }
3671 
3672 /*@
3673   MatMatSolve - Solves A X = B, given a factored matrix.
3674 
3675   Neighbor-wise Collective
3676 
3677   Input Parameters:
3678 + A - the factored matrix
3679 - B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3680 
3681   Output Parameter:
3682 . X - the result matrix (dense matrix)
3683 
3684   Level: developer
3685 
3686   Note:
3687   If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3688   otherwise, `B` and `X` cannot be the same.
3689 
3690 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3691 @*/
3692 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3693 {
3694   PetscFunctionBegin;
3695   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3696   PetscValidType(A, 1);
3697   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3698   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3699   PetscCheckSameComm(A, 1, B, 2);
3700   PetscCheckSameComm(A, 1, X, 3);
3701   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);
3702   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);
3703   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");
3704   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3705   MatCheckPreallocated(A, 1);
3706 
3707   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3708   if (!A->ops->matsolve) {
3709     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3710     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3711   } else PetscUseTypeMethod(A, matsolve, B, X);
3712   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3713   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3714   PetscFunctionReturn(PETSC_SUCCESS);
3715 }
3716 
3717 /*@
3718   MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3719 
3720   Neighbor-wise Collective
3721 
3722   Input Parameters:
3723 + A - the factored matrix
3724 - B - the right-hand-side matrix  (`MATDENSE` matrix)
3725 
3726   Output Parameter:
3727 . X - the result matrix (dense matrix)
3728 
3729   Level: developer
3730 
3731   Note:
3732   The matrices `B` and `X` cannot be the same.  I.e., one cannot
3733   call `MatMatSolveTranspose`(A,X,X).
3734 
3735 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3736 @*/
3737 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3738 {
3739   PetscFunctionBegin;
3740   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3741   PetscValidType(A, 1);
3742   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3743   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3744   PetscCheckSameComm(A, 1, B, 2);
3745   PetscCheckSameComm(A, 1, X, 3);
3746   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3747   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);
3748   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);
3749   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);
3750   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");
3751   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3752   MatCheckPreallocated(A, 1);
3753 
3754   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3755   if (!A->ops->matsolvetranspose) {
3756     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3757     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3758   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3759   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3760   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3761   PetscFunctionReturn(PETSC_SUCCESS);
3762 }
3763 
3764 /*@
3765   MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3766 
3767   Neighbor-wise Collective
3768 
3769   Input Parameters:
3770 + A  - the factored matrix
3771 - Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3772 
3773   Output Parameter:
3774 . X - the result matrix (dense matrix)
3775 
3776   Level: developer
3777 
3778   Note:
3779   For MUMPS, it only supports centralized sparse compressed column format on the host processor for right hand side matrix. User must create B^T in sparse compressed row
3780   format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3781 
3782 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3783 @*/
3784 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3785 {
3786   PetscFunctionBegin;
3787   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3788   PetscValidType(A, 1);
3789   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3790   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3791   PetscCheckSameComm(A, 1, Bt, 2);
3792   PetscCheckSameComm(A, 1, X, 3);
3793 
3794   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3795   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);
3796   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);
3797   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");
3798   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3799   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3800   MatCheckPreallocated(A, 1);
3801 
3802   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3803   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3804   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3805   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3806   PetscFunctionReturn(PETSC_SUCCESS);
3807 }
3808 
3809 /*@
3810   MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3811   U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3812 
3813   Neighbor-wise Collective
3814 
3815   Input Parameters:
3816 + mat - the factored matrix
3817 - b   - the right-hand-side vector
3818 
3819   Output Parameter:
3820 . x - the result vector
3821 
3822   Level: developer
3823 
3824   Notes:
3825   `MatSolve()` should be used for most applications, as it performs
3826   a forward solve followed by a backward solve.
3827 
3828   The vectors `b` and `x` cannot be the same,  i.e., one cannot
3829   call `MatForwardSolve`(A,x,x).
3830 
3831   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3832   the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3833   `MatForwardSolve()` solves U^T*D y = b, and
3834   `MatBackwardSolve()` solves U x = y.
3835   Thus they do not provide a symmetric preconditioner.
3836 
3837 .seealso: [](ch_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`
3838 @*/
3839 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3840 {
3841   PetscFunctionBegin;
3842   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3843   PetscValidType(mat, 1);
3844   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3845   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3846   PetscCheckSameComm(mat, 1, b, 2);
3847   PetscCheckSameComm(mat, 1, x, 3);
3848   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3849   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);
3850   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);
3851   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);
3852   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3853   MatCheckPreallocated(mat, 1);
3854 
3855   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3856   PetscUseTypeMethod(mat, forwardsolve, b, x);
3857   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3858   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3859   PetscFunctionReturn(PETSC_SUCCESS);
3860 }
3861 
3862 /*@
3863   MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3864   D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3865 
3866   Neighbor-wise Collective
3867 
3868   Input Parameters:
3869 + mat - the factored matrix
3870 - b   - the right-hand-side vector
3871 
3872   Output Parameter:
3873 . x - the result vector
3874 
3875   Level: developer
3876 
3877   Notes:
3878   `MatSolve()` should be used for most applications, as it performs
3879   a forward solve followed by a backward solve.
3880 
3881   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3882   call `MatBackwardSolve`(A,x,x).
3883 
3884   For matrix in `MATSEQBAIJ` format with block size larger than 1,
3885   the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3886   `MatForwardSolve()` solves U^T*D y = b, and
3887   `MatBackwardSolve()` solves U x = y.
3888   Thus they do not provide a symmetric preconditioner.
3889 
3890 .seealso: [](ch_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`
3891 @*/
3892 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3893 {
3894   PetscFunctionBegin;
3895   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3896   PetscValidType(mat, 1);
3897   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3898   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3899   PetscCheckSameComm(mat, 1, b, 2);
3900   PetscCheckSameComm(mat, 1, x, 3);
3901   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3902   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);
3903   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);
3904   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);
3905   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3906   MatCheckPreallocated(mat, 1);
3907 
3908   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3909   PetscUseTypeMethod(mat, backwardsolve, b, x);
3910   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3911   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3912   PetscFunctionReturn(PETSC_SUCCESS);
3913 }
3914 
3915 /*@
3916   MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3917 
3918   Neighbor-wise Collective
3919 
3920   Input Parameters:
3921 + mat - the factored matrix
3922 . b   - the right-hand-side vector
3923 - y   - the vector to be added to
3924 
3925   Output Parameter:
3926 . x - the result vector
3927 
3928   Level: developer
3929 
3930   Note:
3931   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3932   call `MatSolveAdd`(A,x,y,x).
3933 
3934 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3935 @*/
3936 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3937 {
3938   PetscScalar one = 1.0;
3939   Vec         tmp;
3940 
3941   PetscFunctionBegin;
3942   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3943   PetscValidType(mat, 1);
3944   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3945   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3946   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3947   PetscCheckSameComm(mat, 1, b, 2);
3948   PetscCheckSameComm(mat, 1, y, 3);
3949   PetscCheckSameComm(mat, 1, x, 4);
3950   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3951   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);
3952   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);
3953   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);
3954   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);
3955   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);
3956   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3957   MatCheckPreallocated(mat, 1);
3958 
3959   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3960   if (mat->factorerrortype) {
3961     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3962     PetscCall(VecSetInf(x));
3963   } else if (mat->ops->solveadd) {
3964     PetscUseTypeMethod(mat, solveadd, b, y, x);
3965   } else {
3966     /* do the solve then the add manually */
3967     if (x != y) {
3968       PetscCall(MatSolve(mat, b, x));
3969       PetscCall(VecAXPY(x, one, y));
3970     } else {
3971       PetscCall(VecDuplicate(x, &tmp));
3972       PetscCall(VecCopy(x, tmp));
3973       PetscCall(MatSolve(mat, b, x));
3974       PetscCall(VecAXPY(x, one, tmp));
3975       PetscCall(VecDestroy(&tmp));
3976     }
3977   }
3978   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3979   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3980   PetscFunctionReturn(PETSC_SUCCESS);
3981 }
3982 
3983 /*@
3984   MatSolveTranspose - Solves A' x = b, given a factored matrix.
3985 
3986   Neighbor-wise Collective
3987 
3988   Input Parameters:
3989 + mat - the factored matrix
3990 - b   - the right-hand-side vector
3991 
3992   Output Parameter:
3993 . x - the result vector
3994 
3995   Level: developer
3996 
3997   Notes:
3998   The vectors `b` and `x` cannot be the same.  I.e., one cannot
3999   call `MatSolveTranspose`(A,x,x).
4000 
4001   Most users should employ the `KSP` interface for linear solvers
4002   instead of working directly with matrix algebra routines such as this.
4003   See, e.g., `KSPCreate()`.
4004 
4005 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
4006 @*/
4007 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
4008 {
4009   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
4010 
4011   PetscFunctionBegin;
4012   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4013   PetscValidType(mat, 1);
4014   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4015   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4016   PetscCheckSameComm(mat, 1, b, 2);
4017   PetscCheckSameComm(mat, 1, x, 3);
4018   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4019   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);
4020   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);
4021   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4022   MatCheckPreallocated(mat, 1);
4023   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4024   if (mat->factorerrortype) {
4025     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4026     PetscCall(VecSetInf(x));
4027   } else {
4028     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4029     PetscCall((*f)(mat, b, x));
4030   }
4031   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4032   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4033   PetscFunctionReturn(PETSC_SUCCESS);
4034 }
4035 
4036 /*@
4037   MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4038   factored matrix.
4039 
4040   Neighbor-wise Collective
4041 
4042   Input Parameters:
4043 + mat - the factored matrix
4044 . b   - the right-hand-side vector
4045 - y   - the vector to be added to
4046 
4047   Output Parameter:
4048 . x - the result vector
4049 
4050   Level: developer
4051 
4052   Note:
4053   The vectors `b` and `x` cannot be the same.  I.e., one cannot
4054   call `MatSolveTransposeAdd`(A,x,y,x).
4055 
4056 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4057 @*/
4058 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4059 {
4060   PetscScalar one = 1.0;
4061   Vec         tmp;
4062   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4063 
4064   PetscFunctionBegin;
4065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4066   PetscValidType(mat, 1);
4067   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4068   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4069   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4070   PetscCheckSameComm(mat, 1, b, 2);
4071   PetscCheckSameComm(mat, 1, y, 3);
4072   PetscCheckSameComm(mat, 1, x, 4);
4073   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4074   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);
4075   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);
4076   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);
4077   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);
4078   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4079   MatCheckPreallocated(mat, 1);
4080 
4081   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4082   if (mat->factorerrortype) {
4083     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4084     PetscCall(VecSetInf(x));
4085   } else if (f) {
4086     PetscCall((*f)(mat, b, y, x));
4087   } else {
4088     /* do the solve then the add manually */
4089     if (x != y) {
4090       PetscCall(MatSolveTranspose(mat, b, x));
4091       PetscCall(VecAXPY(x, one, y));
4092     } else {
4093       PetscCall(VecDuplicate(x, &tmp));
4094       PetscCall(VecCopy(x, tmp));
4095       PetscCall(MatSolveTranspose(mat, b, x));
4096       PetscCall(VecAXPY(x, one, tmp));
4097       PetscCall(VecDestroy(&tmp));
4098     }
4099   }
4100   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4101   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4102   PetscFunctionReturn(PETSC_SUCCESS);
4103 }
4104 
4105 /*@
4106   MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4107 
4108   Neighbor-wise Collective
4109 
4110   Input Parameters:
4111 + mat   - the matrix
4112 . b     - the right hand side
4113 . omega - the relaxation factor
4114 . flag  - flag indicating the type of SOR (see below)
4115 . shift - diagonal shift
4116 . its   - the number of iterations
4117 - lits  - the number of local iterations
4118 
4119   Output Parameter:
4120 . x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4121 
4122   SOR Flags:
4123 +     `SOR_FORWARD_SWEEP` - forward SOR
4124 .     `SOR_BACKWARD_SWEEP` - backward SOR
4125 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4126 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4127 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4128 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4129 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4130 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4131   upper/lower triangular part of matrix to
4132   vector (with omega)
4133 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4134 
4135   Level: developer
4136 
4137   Notes:
4138   `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4139   `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4140   on each processor.
4141 
4142   Application programmers will not generally use `MatSOR()` directly,
4143   but instead will employ the `KSP`/`PC` interface.
4144 
4145   For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4146 
4147   Most users should employ the `KSP` interface for linear solvers
4148   instead of working directly with matrix algebra routines such as this.
4149   See, e.g., `KSPCreate()`.
4150 
4151   Vectors `x` and `b` CANNOT be the same
4152 
4153   The flags are implemented as bitwise inclusive or operations.
4154   For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4155   to specify a zero initial guess for SSOR.
4156 
4157   Developer Notes:
4158   We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4159 
4160 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4161 @*/
4162 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4163 {
4164   PetscFunctionBegin;
4165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4166   PetscValidType(mat, 1);
4167   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4168   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4169   PetscCheckSameComm(mat, 1, b, 2);
4170   PetscCheckSameComm(mat, 1, x, 8);
4171   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4172   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4173   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);
4174   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);
4175   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);
4176   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4177   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4178   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4179 
4180   MatCheckPreallocated(mat, 1);
4181   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4182   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4183   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4184   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4185   PetscFunctionReturn(PETSC_SUCCESS);
4186 }
4187 
4188 /*
4189       Default matrix copy routine.
4190 */
4191 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4192 {
4193   PetscInt           i, rstart = 0, rend = 0, nz;
4194   const PetscInt    *cwork;
4195   const PetscScalar *vwork;
4196 
4197   PetscFunctionBegin;
4198   if (B->assembled) PetscCall(MatZeroEntries(B));
4199   if (str == SAME_NONZERO_PATTERN) {
4200     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4201     for (i = rstart; i < rend; i++) {
4202       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4203       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4204       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4205     }
4206   } else {
4207     PetscCall(MatAYPX(B, 0.0, A, str));
4208   }
4209   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4210   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4211   PetscFunctionReturn(PETSC_SUCCESS);
4212 }
4213 
4214 /*@
4215   MatCopy - Copies a matrix to another matrix.
4216 
4217   Collective
4218 
4219   Input Parameters:
4220 + A   - the matrix
4221 - str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4222 
4223   Output Parameter:
4224 . B - where the copy is put
4225 
4226   Level: intermediate
4227 
4228   Notes:
4229   If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4230 
4231   `MatCopy()` copies the matrix entries of a matrix to another existing
4232   matrix (after first zeroing the second matrix).  A related routine is
4233   `MatConvert()`, which first creates a new matrix and then copies the data.
4234 
4235 .seealso: [](ch_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4236 @*/
4237 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4238 {
4239   PetscInt i;
4240 
4241   PetscFunctionBegin;
4242   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4243   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4244   PetscValidType(A, 1);
4245   PetscValidType(B, 2);
4246   PetscCheckSameComm(A, 1, B, 2);
4247   MatCheckPreallocated(B, 2);
4248   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4249   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4250   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,
4251              A->cmap->N, B->cmap->N);
4252   MatCheckPreallocated(A, 1);
4253   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4254 
4255   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4256   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4257   else PetscCall(MatCopy_Basic(A, B, str));
4258 
4259   B->stencil.dim = A->stencil.dim;
4260   B->stencil.noc = A->stencil.noc;
4261   for (i = 0; i <= A->stencil.dim; i++) {
4262     B->stencil.dims[i]   = A->stencil.dims[i];
4263     B->stencil.starts[i] = A->stencil.starts[i];
4264   }
4265 
4266   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4267   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4268   PetscFunctionReturn(PETSC_SUCCESS);
4269 }
4270 
4271 /*@C
4272   MatConvert - Converts a matrix to another matrix, either of the same
4273   or different type.
4274 
4275   Collective
4276 
4277   Input Parameters:
4278 + mat     - the matrix
4279 . newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4280    same type as the original matrix.
4281 - reuse   - denotes if the destination matrix is to be created or reused.
4282    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
4283    `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).
4284 
4285   Output Parameter:
4286 . M - pointer to place new matrix
4287 
4288   Level: intermediate
4289 
4290   Notes:
4291   `MatConvert()` first creates a new matrix and then copies the data from
4292   the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4293   entries of one matrix to another already existing matrix context.
4294 
4295   Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4296   the MPI communicator of the generated matrix is always the same as the communicator
4297   of the input matrix.
4298 
4299 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4300 @*/
4301 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4302 {
4303   PetscBool  sametype, issame, flg;
4304   PetscBool3 issymmetric, ishermitian;
4305   char       convname[256], mtype[256];
4306   Mat        B;
4307 
4308   PetscFunctionBegin;
4309   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4310   PetscValidType(mat, 1);
4311   PetscValidPointer(M, 4);
4312   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4313   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4314   MatCheckPreallocated(mat, 1);
4315 
4316   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4317   if (flg) newtype = mtype;
4318 
4319   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4320   PetscCall(PetscStrcmp(newtype, "same", &issame));
4321   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4322   PetscCheck(!(reuse == MAT_REUSE_MATRIX) || !(mat == *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_REUSE_MATRIX means reuse matrix in final argument, perhaps you mean MAT_INPLACE_MATRIX");
4323 
4324   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4325     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4326     PetscFunctionReturn(PETSC_SUCCESS);
4327   }
4328 
4329   /* Cache Mat options because some converters use MatHeaderReplace  */
4330   issymmetric = mat->symmetric;
4331   ishermitian = mat->hermitian;
4332 
4333   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4334     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4335     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4336   } else {
4337     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4338     const char *prefix[3]                                 = {"seq", "mpi", ""};
4339     PetscInt    i;
4340     /*
4341        Order of precedence:
4342        0) See if newtype is a superclass of the current matrix.
4343        1) See if a specialized converter is known to the current matrix.
4344        2) See if a specialized converter is known to the desired matrix class.
4345        3) See if a good general converter is registered for the desired class
4346           (as of 6/27/03 only MATMPIADJ falls into this category).
4347        4) See if a good general converter is known for the current matrix.
4348        5) Use a really basic converter.
4349     */
4350 
4351     /* 0) See if newtype is a superclass of the current matrix.
4352           i.e mat is mpiaij and newtype is aij */
4353     for (i = 0; i < 2; i++) {
4354       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4355       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4356       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4357       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4358       if (flg) {
4359         if (reuse == MAT_INPLACE_MATRIX) {
4360           PetscCall(PetscInfo(mat, "Early return\n"));
4361           PetscFunctionReturn(PETSC_SUCCESS);
4362         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4363           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4364           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4365           PetscFunctionReturn(PETSC_SUCCESS);
4366         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4367           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4368           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4369           PetscFunctionReturn(PETSC_SUCCESS);
4370         }
4371       }
4372     }
4373     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4374     for (i = 0; i < 3; i++) {
4375       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4380       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4381       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4382       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4383       if (conv) goto foundconv;
4384     }
4385 
4386     /* 2)  See if a specialized converter is known to the desired matrix class. */
4387     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4388     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4389     PetscCall(MatSetType(B, newtype));
4390     for (i = 0; i < 3; i++) {
4391       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4392       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4393       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4394       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4395       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4396       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4397       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4398       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4399       if (conv) {
4400         PetscCall(MatDestroy(&B));
4401         goto foundconv;
4402       }
4403     }
4404 
4405     /* 3) See if a good general converter is registered for the desired class */
4406     conv = B->ops->convertfrom;
4407     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4408     PetscCall(MatDestroy(&B));
4409     if (conv) goto foundconv;
4410 
4411     /* 4) See if a good general converter is known for the current matrix */
4412     if (mat->ops->convert) conv = mat->ops->convert;
4413     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4414     if (conv) goto foundconv;
4415 
4416     /* 5) Use a really basic converter. */
4417     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4418     conv = MatConvert_Basic;
4419 
4420   foundconv:
4421     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4422     PetscCall((*conv)(mat, newtype, reuse, M));
4423     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4424       /* the block sizes must be same if the mappings are copied over */
4425       (*M)->rmap->bs = mat->rmap->bs;
4426       (*M)->cmap->bs = mat->cmap->bs;
4427       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4428       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4429       (*M)->rmap->mapping = mat->rmap->mapping;
4430       (*M)->cmap->mapping = mat->cmap->mapping;
4431     }
4432     (*M)->stencil.dim = mat->stencil.dim;
4433     (*M)->stencil.noc = mat->stencil.noc;
4434     for (i = 0; i <= mat->stencil.dim; i++) {
4435       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4436       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4437     }
4438     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4439   }
4440   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4441 
4442   /* Copy Mat options */
4443   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4444   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4445   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4446   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4447   PetscFunctionReturn(PETSC_SUCCESS);
4448 }
4449 
4450 /*@C
4451   MatFactorGetSolverType - Returns name of the package providing the factorization routines
4452 
4453   Not Collective
4454 
4455   Input Parameter:
4456 . mat - the matrix, must be a factored matrix
4457 
4458   Output Parameter:
4459 . type - the string name of the package (do not free this string)
4460 
4461   Level: intermediate
4462 
4463   Fortran Notes:
4464   Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4465 
4466 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`
4467 @*/
4468 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4469 {
4470   PetscErrorCode (*conv)(Mat, MatSolverType *);
4471 
4472   PetscFunctionBegin;
4473   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4474   PetscValidType(mat, 1);
4475   PetscValidPointer(type, 2);
4476   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4477   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4478   if (conv) PetscCall((*conv)(mat, type));
4479   else *type = MATSOLVERPETSC;
4480   PetscFunctionReturn(PETSC_SUCCESS);
4481 }
4482 
4483 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4484 struct _MatSolverTypeForSpecifcType {
4485   MatType mtype;
4486   /* no entry for MAT_FACTOR_NONE */
4487   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4488   MatSolverTypeForSpecifcType next;
4489 };
4490 
4491 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4492 struct _MatSolverTypeHolder {
4493   char                       *name;
4494   MatSolverTypeForSpecifcType handlers;
4495   MatSolverTypeHolder         next;
4496 };
4497 
4498 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4499 
4500 /*@C
4501   MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4502 
4503   Input Parameters:
4504 + package      - name of the package, for example petsc or superlu
4505 . mtype        - the matrix type that works with this package
4506 . ftype        - the type of factorization supported by the package
4507 - createfactor - routine that will create the factored matrix ready to be used
4508 
4509   Level: developer
4510 
4511 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4512 @*/
4513 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4514 {
4515   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4516   PetscBool                   flg;
4517   MatSolverTypeForSpecifcType inext, iprev = NULL;
4518 
4519   PetscFunctionBegin;
4520   PetscCall(MatInitializePackage());
4521   if (!next) {
4522     PetscCall(PetscNew(&MatSolverTypeHolders));
4523     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4524     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4525     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4526     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4527     PetscFunctionReturn(PETSC_SUCCESS);
4528   }
4529   while (next) {
4530     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4531     if (flg) {
4532       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4533       inext = next->handlers;
4534       while (inext) {
4535         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4536         if (flg) {
4537           inext->createfactor[(int)ftype - 1] = createfactor;
4538           PetscFunctionReturn(PETSC_SUCCESS);
4539         }
4540         iprev = inext;
4541         inext = inext->next;
4542       }
4543       PetscCall(PetscNew(&iprev->next));
4544       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4545       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4546       PetscFunctionReturn(PETSC_SUCCESS);
4547     }
4548     prev = next;
4549     next = next->next;
4550   }
4551   PetscCall(PetscNew(&prev->next));
4552   PetscCall(PetscStrallocpy(package, &prev->next->name));
4553   PetscCall(PetscNew(&prev->next->handlers));
4554   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4555   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4556   PetscFunctionReturn(PETSC_SUCCESS);
4557 }
4558 
4559 /*@C
4560   MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4561 
4562   Input Parameters:
4563 + type  - name of the package, for example petsc or superlu
4564 . ftype - the type of factorization supported by the type
4565 - mtype - the matrix type that works with this type
4566 
4567   Output Parameters:
4568 + foundtype    - `PETSC_TRUE` if the type was registered
4569 . foundmtype   - `PETSC_TRUE` if the type supports the requested mtype
4570 - createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4571 
4572   Level: developer
4573 
4574 .seealso: [](ch_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4575 @*/
4576 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4577 {
4578   MatSolverTypeHolder         next = MatSolverTypeHolders;
4579   PetscBool                   flg;
4580   MatSolverTypeForSpecifcType inext;
4581 
4582   PetscFunctionBegin;
4583   if (foundtype) *foundtype = PETSC_FALSE;
4584   if (foundmtype) *foundmtype = PETSC_FALSE;
4585   if (createfactor) *createfactor = NULL;
4586 
4587   if (type) {
4588     while (next) {
4589       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4590       if (flg) {
4591         if (foundtype) *foundtype = PETSC_TRUE;
4592         inext = next->handlers;
4593         while (inext) {
4594           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4595           if (flg) {
4596             if (foundmtype) *foundmtype = PETSC_TRUE;
4597             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4598             PetscFunctionReturn(PETSC_SUCCESS);
4599           }
4600           inext = inext->next;
4601         }
4602       }
4603       next = next->next;
4604     }
4605   } else {
4606     while (next) {
4607       inext = next->handlers;
4608       while (inext) {
4609         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4610         if (flg && inext->createfactor[(int)ftype - 1]) {
4611           if (foundtype) *foundtype = PETSC_TRUE;
4612           if (foundmtype) *foundmtype = PETSC_TRUE;
4613           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4614           PetscFunctionReturn(PETSC_SUCCESS);
4615         }
4616         inext = inext->next;
4617       }
4618       next = next->next;
4619     }
4620     /* try with base classes inext->mtype */
4621     next = MatSolverTypeHolders;
4622     while (next) {
4623       inext = next->handlers;
4624       while (inext) {
4625         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4626         if (flg && inext->createfactor[(int)ftype - 1]) {
4627           if (foundtype) *foundtype = PETSC_TRUE;
4628           if (foundmtype) *foundmtype = PETSC_TRUE;
4629           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4630           PetscFunctionReturn(PETSC_SUCCESS);
4631         }
4632         inext = inext->next;
4633       }
4634       next = next->next;
4635     }
4636   }
4637   PetscFunctionReturn(PETSC_SUCCESS);
4638 }
4639 
4640 PetscErrorCode MatSolverTypeDestroy(void)
4641 {
4642   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4643   MatSolverTypeForSpecifcType inext, iprev;
4644 
4645   PetscFunctionBegin;
4646   while (next) {
4647     PetscCall(PetscFree(next->name));
4648     inext = next->handlers;
4649     while (inext) {
4650       PetscCall(PetscFree(inext->mtype));
4651       iprev = inext;
4652       inext = inext->next;
4653       PetscCall(PetscFree(iprev));
4654     }
4655     prev = next;
4656     next = next->next;
4657     PetscCall(PetscFree(prev));
4658   }
4659   MatSolverTypeHolders = NULL;
4660   PetscFunctionReturn(PETSC_SUCCESS);
4661 }
4662 
4663 /*@C
4664   MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4665 
4666   Logically Collective
4667 
4668   Input Parameter:
4669 . mat - the matrix
4670 
4671   Output Parameter:
4672 . flg - `PETSC_TRUE` if uses the ordering
4673 
4674   Level: developer
4675 
4676   Note:
4677   Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4678   packages do not, thus we want to skip generating the ordering when it is not needed or used.
4679 
4680 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4681 @*/
4682 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4683 {
4684   PetscFunctionBegin;
4685   *flg = mat->canuseordering;
4686   PetscFunctionReturn(PETSC_SUCCESS);
4687 }
4688 
4689 /*@C
4690   MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4691 
4692   Logically Collective
4693 
4694   Input Parameters:
4695 + mat   - the matrix obtained with `MatGetFactor()`
4696 - ftype - the factorization type to be used
4697 
4698   Output Parameter:
4699 . otype - the preferred ordering type
4700 
4701   Level: developer
4702 
4703 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4704 @*/
4705 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4706 {
4707   PetscFunctionBegin;
4708   *otype = mat->preferredordering[ftype];
4709   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4710   PetscFunctionReturn(PETSC_SUCCESS);
4711 }
4712 
4713 /*@C
4714   MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4715 
4716   Collective
4717 
4718   Input Parameters:
4719 + mat   - the matrix
4720 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4721 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4722 
4723   Output Parameter:
4724 . f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4725 
4726   Options Database Key:
4727 . -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4728                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4729 
4730   Level: intermediate
4731 
4732   Notes:
4733   The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4734   types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4735 
4736   Users usually access the factorization solvers via `KSP`
4737 
4738   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4739   such as pastix, superlu, mumps etc.
4740 
4741   PETSc must have been ./configure to use the external solver, using the option --download-package
4742 
4743   Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4744   where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4745   call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4746 
4747   Developer Notes:
4748   This should actually be called `MatCreateFactor()` since it creates a new factor object
4749 
4750 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4751           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4752 @*/
4753 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4754 {
4755   PetscBool foundtype, foundmtype;
4756   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4757 
4758   PetscFunctionBegin;
4759   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4760   PetscValidType(mat, 1);
4761 
4762   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4763   MatCheckPreallocated(mat, 1);
4764 
4765   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4766   if (!foundtype) {
4767     if (type) {
4768       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],
4769               ((PetscObject)mat)->type_name, type);
4770     } else {
4771       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);
4772     }
4773   }
4774   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4775   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);
4776 
4777   PetscCall((*conv)(mat, ftype, f));
4778   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4779   PetscFunctionReturn(PETSC_SUCCESS);
4780 }
4781 
4782 /*@C
4783   MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4784 
4785   Not Collective
4786 
4787   Input Parameters:
4788 + mat   - the matrix
4789 . type  - name of solver type, for example, superlu, petsc (to use PETSc's default)
4790 - ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4791 
4792   Output Parameter:
4793 . flg - PETSC_TRUE if the factorization is available
4794 
4795   Level: intermediate
4796 
4797   Notes:
4798   Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4799   such as pastix, superlu, mumps etc.
4800 
4801   PETSc must have been ./configure to use the external solver, using the option --download-package
4802 
4803   Developer Notes:
4804   This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4805 
4806 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatSolverTypeRegister()`,
4807           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4808 @*/
4809 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4810 {
4811   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4812 
4813   PetscFunctionBegin;
4814   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4815   PetscValidType(mat, 1);
4816   PetscValidBoolPointer(flg, 4);
4817 
4818   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4819   MatCheckPreallocated(mat, 1);
4820 
4821   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4822   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4823   PetscFunctionReturn(PETSC_SUCCESS);
4824 }
4825 
4826 /*@
4827   MatDuplicate - Duplicates a matrix including the non-zero structure.
4828 
4829   Collective
4830 
4831   Input Parameters:
4832 + mat - the matrix
4833 - op  - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4834         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4835 
4836   Output Parameter:
4837 . M - pointer to place new matrix
4838 
4839   Level: intermediate
4840 
4841   Notes:
4842   You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4843 
4844   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.
4845 
4846   When original mat is a product of matrix operation, e.g., an output of `MatMatMult()` or `MatCreateSubMatrix()`, only the simple matrix data structure of mat
4847   is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4848   User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4849 
4850 .seealso: [](ch_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4851 @*/
4852 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4853 {
4854   Mat         B;
4855   VecType     vtype;
4856   PetscInt    i;
4857   PetscObject dm, container_h, container_d;
4858   void (*viewf)(void);
4859 
4860   PetscFunctionBegin;
4861   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4862   PetscValidType(mat, 1);
4863   PetscValidPointer(M, 3);
4864   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4865   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4866   MatCheckPreallocated(mat, 1);
4867 
4868   *M = NULL;
4869   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4870   PetscUseTypeMethod(mat, duplicate, op, M);
4871   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4872   B = *M;
4873 
4874   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4875   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4876   PetscCall(MatGetVecType(mat, &vtype));
4877   PetscCall(MatSetVecType(B, vtype));
4878 
4879   B->stencil.dim = mat->stencil.dim;
4880   B->stencil.noc = mat->stencil.noc;
4881   for (i = 0; i <= mat->stencil.dim; i++) {
4882     B->stencil.dims[i]   = mat->stencil.dims[i];
4883     B->stencil.starts[i] = mat->stencil.starts[i];
4884   }
4885 
4886   B->nooffproczerorows = mat->nooffproczerorows;
4887   B->nooffprocentries  = mat->nooffprocentries;
4888 
4889   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4890   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4891   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4892   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4893   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4894   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4895   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4896   PetscFunctionReturn(PETSC_SUCCESS);
4897 }
4898 
4899 /*@
4900   MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4901 
4902   Logically Collective
4903 
4904   Input Parameter:
4905 . mat - the matrix
4906 
4907   Output Parameter:
4908 . v - the diagonal of the matrix
4909 
4910   Level: intermediate
4911 
4912   Note:
4913   If `mat` has local sizes `n` x `m`, this routine fills the first `ndiag = min(n, m)` entries
4914   of `v` with the diagonal values. Thus `v` must have local size of at least `ndiag`. If `v`
4915   is larger than `ndiag`, the values of the remaining entries are unspecified.
4916 
4917   Currently only correct in parallel for square matrices.
4918 
4919 .seealso: [](ch_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4920 @*/
4921 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4922 {
4923   PetscFunctionBegin;
4924   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4925   PetscValidType(mat, 1);
4926   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4927   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4928   MatCheckPreallocated(mat, 1);
4929   if (PetscDefined(USE_DEBUG)) {
4930     PetscInt nv, row, col, ndiag;
4931 
4932     PetscCall(VecGetLocalSize(v, &nv));
4933     PetscCall(MatGetLocalSize(mat, &row, &col));
4934     ndiag = PetscMin(row, col);
4935     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);
4936   }
4937 
4938   PetscUseTypeMethod(mat, getdiagonal, v);
4939   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4940   PetscFunctionReturn(PETSC_SUCCESS);
4941 }
4942 
4943 /*@C
4944   MatGetRowMin - Gets the minimum value (of the real part) of each
4945   row of the matrix
4946 
4947   Logically Collective
4948 
4949   Input Parameter:
4950 . mat - the matrix
4951 
4952   Output Parameters:
4953 + v   - the vector for storing the maximums
4954 - idx - the indices of the column found for each row (optional)
4955 
4956   Level: intermediate
4957 
4958   Note:
4959   The result of this call are the same as if one converted the matrix to dense format
4960   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4961 
4962   This code is only implemented for a couple of matrix formats.
4963 
4964 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4965           `MatGetRowMax()`
4966 @*/
4967 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4968 {
4969   PetscFunctionBegin;
4970   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4971   PetscValidType(mat, 1);
4972   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4973   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4974 
4975   if (!mat->cmap->N) {
4976     PetscCall(VecSet(v, PETSC_MAX_REAL));
4977     if (idx) {
4978       PetscInt i, m = mat->rmap->n;
4979       for (i = 0; i < m; i++) idx[i] = -1;
4980     }
4981   } else {
4982     MatCheckPreallocated(mat, 1);
4983   }
4984   PetscUseTypeMethod(mat, getrowmin, v, idx);
4985   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4986   PetscFunctionReturn(PETSC_SUCCESS);
4987 }
4988 
4989 /*@C
4990   MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4991   row of the matrix
4992 
4993   Logically Collective
4994 
4995   Input Parameter:
4996 . mat - the matrix
4997 
4998   Output Parameters:
4999 + v   - the vector for storing the minimums
5000 - idx - the indices of the column found for each row (or `NULL` if not needed)
5001 
5002   Level: intermediate
5003 
5004   Notes:
5005   if a row is completely empty or has only 0.0 values then the idx[] value for that
5006   row is 0 (the first column).
5007 
5008   This code is only implemented for a couple of matrix formats.
5009 
5010 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
5011 @*/
5012 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
5013 {
5014   PetscFunctionBegin;
5015   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5016   PetscValidType(mat, 1);
5017   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5018   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5019   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5020 
5021   if (!mat->cmap->N) {
5022     PetscCall(VecSet(v, 0.0));
5023     if (idx) {
5024       PetscInt i, m = mat->rmap->n;
5025       for (i = 0; i < m; i++) idx[i] = -1;
5026     }
5027   } else {
5028     MatCheckPreallocated(mat, 1);
5029     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5030     PetscUseTypeMethod(mat, getrowminabs, v, idx);
5031   }
5032   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5033   PetscFunctionReturn(PETSC_SUCCESS);
5034 }
5035 
5036 /*@C
5037   MatGetRowMax - Gets the maximum value (of the real part) of each
5038   row of the matrix
5039 
5040   Logically Collective
5041 
5042   Input Parameter:
5043 . mat - the matrix
5044 
5045   Output Parameters:
5046 + v   - the vector for storing the maximums
5047 - idx - the indices of the column found for each row (optional)
5048 
5049   Level: intermediate
5050 
5051   Notes:
5052   The result of this call are the same as if one converted the matrix to dense format
5053   and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5054 
5055   This code is only implemented for a couple of matrix formats.
5056 
5057 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5058 @*/
5059 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5060 {
5061   PetscFunctionBegin;
5062   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5063   PetscValidType(mat, 1);
5064   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5065   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5066 
5067   if (!mat->cmap->N) {
5068     PetscCall(VecSet(v, PETSC_MIN_REAL));
5069     if (idx) {
5070       PetscInt i, m = mat->rmap->n;
5071       for (i = 0; i < m; i++) idx[i] = -1;
5072     }
5073   } else {
5074     MatCheckPreallocated(mat, 1);
5075     PetscUseTypeMethod(mat, getrowmax, v, idx);
5076   }
5077   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5078   PetscFunctionReturn(PETSC_SUCCESS);
5079 }
5080 
5081 /*@C
5082   MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5083   row of the matrix
5084 
5085   Logically Collective
5086 
5087   Input Parameter:
5088 . mat - the matrix
5089 
5090   Output Parameters:
5091 + v   - the vector for storing the maximums
5092 - idx - the indices of the column found for each row (or `NULL` if not needed)
5093 
5094   Level: intermediate
5095 
5096   Notes:
5097   if a row is completely empty or has only 0.0 values then the idx[] value for that
5098   row is 0 (the first column).
5099 
5100   This code is only implemented for a couple of matrix formats.
5101 
5102 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5103 @*/
5104 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5105 {
5106   PetscFunctionBegin;
5107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5108   PetscValidType(mat, 1);
5109   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5110   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5111 
5112   if (!mat->cmap->N) {
5113     PetscCall(VecSet(v, 0.0));
5114     if (idx) {
5115       PetscInt i, m = mat->rmap->n;
5116       for (i = 0; i < m; i++) idx[i] = -1;
5117     }
5118   } else {
5119     MatCheckPreallocated(mat, 1);
5120     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5121     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5122   }
5123   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5124   PetscFunctionReturn(PETSC_SUCCESS);
5125 }
5126 
5127 /*@
5128   MatGetRowSum - Gets the sum of each row of the matrix
5129 
5130   Logically or Neighborhood Collective
5131 
5132   Input Parameter:
5133 . mat - the matrix
5134 
5135   Output Parameter:
5136 . v - the vector for storing the sum of rows
5137 
5138   Level: intermediate
5139 
5140   Notes:
5141   This code is slow since it is not currently specialized for different formats
5142 
5143 .seealso: [](ch_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5144 @*/
5145 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5146 {
5147   Vec ones;
5148 
5149   PetscFunctionBegin;
5150   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5151   PetscValidType(mat, 1);
5152   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5153   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5154   MatCheckPreallocated(mat, 1);
5155   PetscCall(MatCreateVecs(mat, &ones, NULL));
5156   PetscCall(VecSet(ones, 1.));
5157   PetscCall(MatMult(mat, ones, v));
5158   PetscCall(VecDestroy(&ones));
5159   PetscFunctionReturn(PETSC_SUCCESS);
5160 }
5161 
5162 /*@
5163   MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5164   when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5165 
5166   Collective
5167 
5168   Input Parameter:
5169 . mat - the matrix to provide the transpose
5170 
5171   Output Parameter:
5172 . mat - 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
5173 
5174   Level: advanced
5175 
5176   Note:
5177   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
5178   routine allows bypassing that call.
5179 
5180 .seealso: [](ch_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5181 @*/
5182 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5183 {
5184   PetscContainer  rB = NULL;
5185   MatParentState *rb = NULL;
5186 
5187   PetscFunctionBegin;
5188   PetscCall(PetscNew(&rb));
5189   rb->id    = ((PetscObject)mat)->id;
5190   rb->state = 0;
5191   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5192   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5193   PetscCall(PetscContainerSetPointer(rB, rb));
5194   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5195   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5196   PetscCall(PetscObjectDereference((PetscObject)rB));
5197   PetscFunctionReturn(PETSC_SUCCESS);
5198 }
5199 
5200 /*@
5201   MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5202 
5203   Collective
5204 
5205   Input Parameters:
5206 + mat   - the matrix to transpose
5207 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5208 
5209   Output Parameter:
5210 . B - the transpose
5211 
5212   Level: intermediate
5213 
5214   Notes:
5215   If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5216 
5217   `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
5218   transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5219 
5220   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.
5221 
5222   Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5223 
5224   If mat is unchanged from the last call this function returns immediately without recomputing the result
5225 
5226   If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5227 
5228 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5229           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5230 @*/
5231 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5232 {
5233   PetscContainer  rB = NULL;
5234   MatParentState *rb = NULL;
5235 
5236   PetscFunctionBegin;
5237   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5238   PetscValidType(mat, 1);
5239   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5240   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5241   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5242   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5243   MatCheckPreallocated(mat, 1);
5244   if (reuse == MAT_REUSE_MATRIX) {
5245     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5246     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5247     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5248     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5249     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5250   }
5251 
5252   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5253   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5254     PetscUseTypeMethod(mat, transpose, reuse, B);
5255     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5256   }
5257   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5258 
5259   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5260   if (reuse != MAT_INPLACE_MATRIX) {
5261     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5262     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5263     rb->state        = ((PetscObject)mat)->state;
5264     rb->nonzerostate = mat->nonzerostate;
5265   }
5266   PetscFunctionReturn(PETSC_SUCCESS);
5267 }
5268 
5269 /*@
5270   MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5271 
5272   Collective
5273 
5274   Input Parameter:
5275 . A - the matrix to transpose
5276 
5277   Output Parameter:
5278 . 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
5279       numerical portion.
5280 
5281   Level: intermediate
5282 
5283   Note:
5284   This is not supported for many matrix types, use `MatTranspose()` in those cases
5285 
5286 .seealso: [](ch_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5287 @*/
5288 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5289 {
5290   PetscFunctionBegin;
5291   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5292   PetscValidType(A, 1);
5293   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5294   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5295   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5296   PetscUseTypeMethod(A, transposesymbolic, B);
5297   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5298 
5299   PetscCall(MatTransposeSetPrecursor(A, *B));
5300   PetscFunctionReturn(PETSC_SUCCESS);
5301 }
5302 
5303 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5304 {
5305   PetscContainer  rB;
5306   MatParentState *rb;
5307 
5308   PetscFunctionBegin;
5309   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5310   PetscValidType(A, 1);
5311   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5312   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5313   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5314   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5315   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5316   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5317   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5318   PetscFunctionReturn(PETSC_SUCCESS);
5319 }
5320 
5321 /*@
5322   MatIsTranspose - Test whether a matrix is another one's transpose,
5323   or its own, in which case it tests symmetry.
5324 
5325   Collective
5326 
5327   Input Parameters:
5328 + A   - the matrix to test
5329 . B   - the matrix to test against, this can equal the first parameter
5330 - tol - tolerance, differences between entries smaller than this are counted as zero
5331 
5332   Output Parameter:
5333 . flg - the result
5334 
5335   Level: intermediate
5336 
5337   Notes:
5338   Only available for `MATAIJ` matrices.
5339 
5340   The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5341   test involves parallel copies of the block-offdiagonal parts of the matrix.
5342 
5343 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5344 @*/
5345 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5346 {
5347   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5348 
5349   PetscFunctionBegin;
5350   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5351   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5352   PetscValidBoolPointer(flg, 4);
5353   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5354   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5355   *flg = PETSC_FALSE;
5356   if (f && g) {
5357     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5358     PetscCall((*f)(A, B, tol, flg));
5359   } else {
5360     MatType mattype;
5361 
5362     PetscCall(MatGetType(f ? B : A, &mattype));
5363     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5364   }
5365   PetscFunctionReturn(PETSC_SUCCESS);
5366 }
5367 
5368 /*@
5369   MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5370 
5371   Collective
5372 
5373   Input Parameters:
5374 + mat   - the matrix to transpose and complex conjugate
5375 - reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5376 
5377   Output Parameter:
5378 . B - the Hermitian transpose
5379 
5380   Level: intermediate
5381 
5382 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5383 @*/
5384 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5385 {
5386   PetscFunctionBegin;
5387   PetscCall(MatTranspose(mat, reuse, B));
5388 #if defined(PETSC_USE_COMPLEX)
5389   PetscCall(MatConjugate(*B));
5390 #endif
5391   PetscFunctionReturn(PETSC_SUCCESS);
5392 }
5393 
5394 /*@
5395   MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5396 
5397   Collective
5398 
5399   Input Parameters:
5400 + A   - the matrix to test
5401 . B   - the matrix to test against, this can equal the first parameter
5402 - tol - tolerance, differences between entries smaller than this are counted as zero
5403 
5404   Output Parameter:
5405 . flg - the result
5406 
5407   Level: intermediate
5408 
5409   Notes:
5410   Only available for `MATAIJ` matrices.
5411 
5412   The sequential algorithm
5413   has a running time of the order of the number of nonzeros; the parallel
5414   test involves parallel copies of the block-offdiagonal parts of the matrix.
5415 
5416 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5417 @*/
5418 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5419 {
5420   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5421 
5422   PetscFunctionBegin;
5423   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5424   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5425   PetscValidBoolPointer(flg, 4);
5426   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5427   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5428   if (f && g) {
5429     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5430     PetscCall((*f)(A, B, tol, flg));
5431   }
5432   PetscFunctionReturn(PETSC_SUCCESS);
5433 }
5434 
5435 /*@
5436   MatPermute - Creates a new matrix with rows and columns permuted from the
5437   original.
5438 
5439   Collective
5440 
5441   Input Parameters:
5442 + mat - the matrix to permute
5443 . row - row permutation, each processor supplies only the permutation for its rows
5444 - col - column permutation, each processor supplies only the permutation for its columns
5445 
5446   Output Parameter:
5447 . B - the permuted matrix
5448 
5449   Level: advanced
5450 
5451   Note:
5452   The index sets map from row/col of permuted matrix to row/col of original matrix.
5453   The index sets should be on the same communicator as mat and have the same local sizes.
5454 
5455   Developer Notes:
5456   If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5457   exploit the fact that row and col are permutations, consider implementing the
5458   more general `MatCreateSubMatrix()` instead.
5459 
5460 .seealso: [](ch_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5461 @*/
5462 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5463 {
5464   PetscFunctionBegin;
5465   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5466   PetscValidType(mat, 1);
5467   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5468   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5469   PetscValidPointer(B, 4);
5470   PetscCheckSameComm(mat, 1, row, 2);
5471   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5472   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5473   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5474   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5475   MatCheckPreallocated(mat, 1);
5476 
5477   if (mat->ops->permute) {
5478     PetscUseTypeMethod(mat, permute, row, col, B);
5479     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5480   } else {
5481     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5482   }
5483   PetscFunctionReturn(PETSC_SUCCESS);
5484 }
5485 
5486 /*@
5487   MatEqual - Compares two matrices.
5488 
5489   Collective
5490 
5491   Input Parameters:
5492 + A - the first matrix
5493 - B - the second matrix
5494 
5495   Output Parameter:
5496 . flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5497 
5498   Level: intermediate
5499 
5500 .seealso: [](ch_matrices), `Mat`
5501 @*/
5502 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5503 {
5504   PetscFunctionBegin;
5505   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5506   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5507   PetscValidType(A, 1);
5508   PetscValidType(B, 2);
5509   PetscValidBoolPointer(flg, 3);
5510   PetscCheckSameComm(A, 1, B, 2);
5511   MatCheckPreallocated(A, 1);
5512   MatCheckPreallocated(B, 2);
5513   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5514   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5515   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,
5516              B->cmap->N);
5517   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5518     PetscUseTypeMethod(A, equal, B, flg);
5519   } else {
5520     PetscCall(MatMultEqual(A, B, 10, flg));
5521   }
5522   PetscFunctionReturn(PETSC_SUCCESS);
5523 }
5524 
5525 /*@
5526   MatDiagonalScale - Scales a matrix on the left and right by diagonal
5527   matrices that are stored as vectors.  Either of the two scaling
5528   matrices can be `NULL`.
5529 
5530   Collective
5531 
5532   Input Parameters:
5533 + mat - the matrix to be scaled
5534 . l   - the left scaling vector (or `NULL`)
5535 - r   - the right scaling vector (or `NULL`)
5536 
5537   Level: intermediate
5538 
5539   Note:
5540   `MatDiagonalScale()` computes A = LAR, where
5541   L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5542   The L scales the rows of the matrix, the R scales the columns of the matrix.
5543 
5544 .seealso: [](ch_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5545 @*/
5546 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5547 {
5548   PetscFunctionBegin;
5549   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5550   PetscValidType(mat, 1);
5551   if (l) {
5552     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5553     PetscCheckSameComm(mat, 1, l, 2);
5554   }
5555   if (r) {
5556     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5557     PetscCheckSameComm(mat, 1, r, 3);
5558   }
5559   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5560   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5561   MatCheckPreallocated(mat, 1);
5562   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5563 
5564   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5565   PetscUseTypeMethod(mat, diagonalscale, l, r);
5566   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5567   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5568   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5569   PetscFunctionReturn(PETSC_SUCCESS);
5570 }
5571 
5572 /*@
5573   MatScale - Scales all elements of a matrix by a given number.
5574 
5575   Logically Collective
5576 
5577   Input Parameters:
5578 + mat - the matrix to be scaled
5579 - a   - the scaling value
5580 
5581   Level: intermediate
5582 
5583 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
5584 @*/
5585 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5586 {
5587   PetscFunctionBegin;
5588   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5589   PetscValidType(mat, 1);
5590   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5591   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5592   PetscValidLogicalCollectiveScalar(mat, a, 2);
5593   MatCheckPreallocated(mat, 1);
5594 
5595   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5596   if (a != (PetscScalar)1.0) {
5597     PetscUseTypeMethod(mat, scale, a);
5598     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5599   }
5600   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5601   PetscFunctionReturn(PETSC_SUCCESS);
5602 }
5603 
5604 /*@
5605   MatNorm - Calculates various norms of a matrix.
5606 
5607   Collective
5608 
5609   Input Parameters:
5610 + mat  - the matrix
5611 - type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5612 
5613   Output Parameter:
5614 . nrm - the resulting norm
5615 
5616   Level: intermediate
5617 
5618 .seealso: [](ch_matrices), `Mat`
5619 @*/
5620 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5621 {
5622   PetscFunctionBegin;
5623   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5624   PetscValidType(mat, 1);
5625   PetscValidRealPointer(nrm, 3);
5626 
5627   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5628   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5629   MatCheckPreallocated(mat, 1);
5630 
5631   PetscUseTypeMethod(mat, norm, type, nrm);
5632   PetscFunctionReturn(PETSC_SUCCESS);
5633 }
5634 
5635 /*
5636      This variable is used to prevent counting of MatAssemblyBegin() that
5637    are called from within a MatAssemblyEnd().
5638 */
5639 static PetscInt MatAssemblyEnd_InUse = 0;
5640 /*@
5641   MatAssemblyBegin - Begins assembling the matrix.  This routine should
5642   be called after completing all calls to `MatSetValues()`.
5643 
5644   Collective
5645 
5646   Input Parameters:
5647 + mat  - the matrix
5648 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5649 
5650   Level: beginner
5651 
5652   Notes:
5653   `MatSetValues()` generally caches the values that belong to other MPI processes.  The matrix is ready to
5654   use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5655 
5656   Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5657   in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5658   using the matrix.
5659 
5660   ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5661   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
5662   a global collective operation requiring all processes that share the matrix.
5663 
5664   Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5665   out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5666   before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5667 
5668 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5669 @*/
5670 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5671 {
5672   PetscFunctionBegin;
5673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5674   PetscValidType(mat, 1);
5675   MatCheckPreallocated(mat, 1);
5676   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5677   if (mat->assembled) {
5678     mat->was_assembled = PETSC_TRUE;
5679     mat->assembled     = PETSC_FALSE;
5680   }
5681 
5682   if (!MatAssemblyEnd_InUse) {
5683     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5684     PetscTryTypeMethod(mat, assemblybegin, type);
5685     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5686   } else PetscTryTypeMethod(mat, assemblybegin, type);
5687   PetscFunctionReturn(PETSC_SUCCESS);
5688 }
5689 
5690 /*@
5691   MatAssembled - Indicates if a matrix has been assembled and is ready for
5692   use; for example, in matrix-vector product.
5693 
5694   Not Collective
5695 
5696   Input Parameter:
5697 . mat - the matrix
5698 
5699   Output Parameter:
5700 . assembled - `PETSC_TRUE` or `PETSC_FALSE`
5701 
5702   Level: advanced
5703 
5704 .seealso: [](ch_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5705 @*/
5706 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5707 {
5708   PetscFunctionBegin;
5709   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5710   PetscValidBoolPointer(assembled, 2);
5711   *assembled = mat->assembled;
5712   PetscFunctionReturn(PETSC_SUCCESS);
5713 }
5714 
5715 /*@
5716   MatAssemblyEnd - Completes assembling the matrix.  This routine should
5717   be called after `MatAssemblyBegin()`.
5718 
5719   Collective
5720 
5721   Input Parameters:
5722 + mat  - the matrix
5723 - type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5724 
5725   Options Database Keys:
5726 + -mat_view ::ascii_info             - Prints info on matrix at conclusion of `MatAssemblyEnd()`
5727 . -mat_view ::ascii_info_detail      - Prints more detailed info
5728 . -mat_view                          - Prints matrix in ASCII format
5729 . -mat_view ::ascii_matlab           - Prints matrix in Matlab format
5730 . -mat_view draw                     - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5731 . -display <name>                    - Sets display name (default is host)
5732 . -draw_pause <sec>                  - Sets number of seconds to pause after display
5733 . -mat_view socket                   - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5734 . -viewer_socket_machine <machine>   - Machine to use for socket
5735 . -viewer_socket_port <port>         - Port number to use for socket
5736 - -mat_view binary:filename[:append] - Save matrix to file in binary format
5737 
5738   Level: beginner
5739 
5740 .seealso: [](ch_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5741 @*/
5742 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5743 {
5744   static PetscInt inassm = 0;
5745   PetscBool       flg    = PETSC_FALSE;
5746 
5747   PetscFunctionBegin;
5748   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5749   PetscValidType(mat, 1);
5750 
5751   inassm++;
5752   MatAssemblyEnd_InUse++;
5753   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5754     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5755     PetscTryTypeMethod(mat, assemblyend, type);
5756     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5757   } else PetscTryTypeMethod(mat, assemblyend, type);
5758 
5759   /* Flush assembly is not a true assembly */
5760   if (type != MAT_FLUSH_ASSEMBLY) {
5761     if (mat->num_ass) {
5762       if (!mat->symmetry_eternal) {
5763         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5764         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5765       }
5766       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5767       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5768     }
5769     mat->num_ass++;
5770     mat->assembled        = PETSC_TRUE;
5771     mat->ass_nonzerostate = mat->nonzerostate;
5772   }
5773 
5774   mat->insertmode = NOT_SET_VALUES;
5775   MatAssemblyEnd_InUse--;
5776   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5777   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5778     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5779 
5780     if (mat->checksymmetryonassembly) {
5781       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5782       if (flg) {
5783         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5784       } else {
5785         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5786       }
5787     }
5788     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5789   }
5790   inassm--;
5791   PetscFunctionReturn(PETSC_SUCCESS);
5792 }
5793 
5794 /*@
5795   MatSetOption - Sets a parameter option for a matrix. Some options
5796   may be specific to certain storage formats.  Some options
5797   determine how values will be inserted (or added). Sorted,
5798   row-oriented input will generally assemble the fastest. The default
5799   is row-oriented.
5800 
5801   Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5802 
5803   Input Parameters:
5804 + mat - the matrix
5805 . op  - the option, one of those listed below (and possibly others),
5806 - flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5807 
5808   Options Describing Matrix Structure:
5809 + `MAT_SPD`                         - symmetric positive definite
5810 . `MAT_SYMMETRIC`                   - symmetric in terms of both structure and value
5811 . `MAT_HERMITIAN`                   - transpose is the complex conjugation
5812 . `MAT_STRUCTURALLY_SYMMETRIC`      - symmetric nonzero structure
5813 . `MAT_SYMMETRY_ETERNAL`            - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5814 . `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5815 . `MAT_SPD_ETERNAL`                 - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5816 
5817    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5818    do not need to be computed (usually at a high cost)
5819 
5820    Options For Use with `MatSetValues()`:
5821    Insert a logically dense subblock, which can be
5822 . `MAT_ROW_ORIENTED`                - row-oriented (default)
5823 
5824    These options reflect the data you pass in with `MatSetValues()`; it has
5825    nothing to do with how the data is stored internally in the matrix
5826    data structure.
5827 
5828    When (re)assembling a matrix, we can restrict the input for
5829    efficiency/debugging purposes.  These options include
5830 . `MAT_NEW_NONZERO_LOCATIONS`       - additional insertions will be allowed if they generate a new nonzero (slow)
5831 . `MAT_FORCE_DIAGONAL_ENTRIES`      - forces diagonal entries to be allocated
5832 . `MAT_IGNORE_OFF_PROC_ENTRIES`     - drops off-processor entries
5833 . `MAT_NEW_NONZERO_LOCATION_ERR`    - generates an error for new matrix entry
5834 . `MAT_USE_HASH_TABLE`              - uses a hash table to speed up matrix assembly
5835 . `MAT_NO_OFF_PROC_ENTRIES`         - you know each process will only set values for its own rows, will generate an error if
5836         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5837         performance for very large process counts.
5838 - `MAT_SUBSET_OFF_PROC_ENTRIES`     - you know that the first assembly after setting this flag will set a superset
5839         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5840         functions, instead sending only neighbor messages.
5841 
5842   Level: intermediate
5843 
5844   Notes:
5845   Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5846 
5847   Some options are relevant only for particular matrix types and
5848   are thus ignored by others.  Other options are not supported by
5849   certain matrix types and will generate an error message if set.
5850 
5851   If using Fortran to compute a matrix, one may need to
5852   use the column-oriented option (or convert to the row-oriented
5853   format).
5854 
5855   `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5856   that would generate a new entry in the nonzero structure is instead
5857   ignored.  Thus, if memory has not already been allocated for this particular
5858   data, then the insertion is ignored. For dense matrices, in which
5859   the entire array is allocated, no entries are ever ignored.
5860   Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5861 
5862   `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5863   that would generate a new entry in the nonzero structure instead produces
5864   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
5865 
5866   `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5867   that would generate a new entry that has not been preallocated will
5868   instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5869   only.) This is a useful flag when debugging matrix memory preallocation.
5870   If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5871 
5872   `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5873   other processors should be dropped, rather than stashed.
5874   This is useful if you know that the "owning" processor is also
5875   always generating the correct matrix entries, so that PETSc need
5876   not transfer duplicate entries generated on another processor.
5877 
5878   `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5879   searches during matrix assembly. When this flag is set, the hash table
5880   is created during the first matrix assembly. This hash table is
5881   used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5882   to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5883   should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5884   supported by `MATMPIBAIJ` format only.
5885 
5886   `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5887   are kept in the nonzero structure
5888 
5889   `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5890   a zero location in the matrix
5891 
5892   `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5893 
5894   `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5895   zero row routines and thus improves performance for very large process counts.
5896 
5897   `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5898   part of the matrix (since they should match the upper triangular part).
5899 
5900   `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5901   single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5902   with finite difference schemes with non-periodic boundary conditions.
5903 
5904   Developer Notes:
5905   `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5906   places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5907   to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5908   not changed.
5909 
5910 .seealso: [](ch_matrices), `MatOption`, `Mat`, `MatGetOption()`
5911 @*/
5912 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5913 {
5914   PetscFunctionBegin;
5915   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5916   if (op > 0) {
5917     PetscValidLogicalCollectiveEnum(mat, op, 2);
5918     PetscValidLogicalCollectiveBool(mat, flg, 3);
5919   }
5920 
5921   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);
5922 
5923   switch (op) {
5924   case MAT_FORCE_DIAGONAL_ENTRIES:
5925     mat->force_diagonals = flg;
5926     PetscFunctionReturn(PETSC_SUCCESS);
5927   case MAT_NO_OFF_PROC_ENTRIES:
5928     mat->nooffprocentries = flg;
5929     PetscFunctionReturn(PETSC_SUCCESS);
5930   case MAT_SUBSET_OFF_PROC_ENTRIES:
5931     mat->assembly_subset = flg;
5932     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5933 #if !defined(PETSC_HAVE_MPIUNI)
5934       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5935 #endif
5936       mat->stash.first_assembly_done = PETSC_FALSE;
5937     }
5938     PetscFunctionReturn(PETSC_SUCCESS);
5939   case MAT_NO_OFF_PROC_ZERO_ROWS:
5940     mat->nooffproczerorows = flg;
5941     PetscFunctionReturn(PETSC_SUCCESS);
5942   case MAT_SPD:
5943     if (flg) {
5944       mat->spd                    = PETSC_BOOL3_TRUE;
5945       mat->symmetric              = PETSC_BOOL3_TRUE;
5946       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5947     } else {
5948       mat->spd = PETSC_BOOL3_FALSE;
5949     }
5950     break;
5951   case MAT_SYMMETRIC:
5952     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5953     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5954 #if !defined(PETSC_USE_COMPLEX)
5955     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5956 #endif
5957     break;
5958   case MAT_HERMITIAN:
5959     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5960     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5961 #if !defined(PETSC_USE_COMPLEX)
5962     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5963 #endif
5964     break;
5965   case MAT_STRUCTURALLY_SYMMETRIC:
5966     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5967     break;
5968   case MAT_SYMMETRY_ETERNAL:
5969     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");
5970     mat->symmetry_eternal = flg;
5971     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5972     break;
5973   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5974     PetscCheck(mat->structurally_symmetric != PETSC_BOOL3_UNKNOWN, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot set MAT_STRUCTURAL_SYMMETRY_ETERNAL without first setting MAT_STRUCTURAL_SYMMETRIC to true or false");
5975     mat->structural_symmetry_eternal = flg;
5976     break;
5977   case MAT_SPD_ETERNAL:
5978     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");
5979     mat->spd_eternal = flg;
5980     if (flg) {
5981       mat->structural_symmetry_eternal = PETSC_TRUE;
5982       mat->symmetry_eternal            = PETSC_TRUE;
5983     }
5984     break;
5985   case MAT_STRUCTURE_ONLY:
5986     mat->structure_only = flg;
5987     break;
5988   case MAT_SORTED_FULL:
5989     mat->sortedfull = flg;
5990     break;
5991   default:
5992     break;
5993   }
5994   PetscTryTypeMethod(mat, setoption, op, flg);
5995   PetscFunctionReturn(PETSC_SUCCESS);
5996 }
5997 
5998 /*@
5999   MatGetOption - Gets a parameter option that has been set for a matrix.
6000 
6001   Logically Collective
6002 
6003   Input Parameters:
6004 + mat - the matrix
6005 - op  - the option, this only responds to certain options, check the code for which ones
6006 
6007   Output Parameter:
6008 . flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
6009 
6010   Level: intermediate
6011 
6012   Notes:
6013   Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
6014 
6015   Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
6016   `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6017 
6018 .seealso: [](ch_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
6019     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
6020 @*/
6021 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
6022 {
6023   PetscFunctionBegin;
6024   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6025   PetscValidType(mat, 1);
6026 
6027   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);
6028   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()");
6029 
6030   switch (op) {
6031   case MAT_NO_OFF_PROC_ENTRIES:
6032     *flg = mat->nooffprocentries;
6033     break;
6034   case MAT_NO_OFF_PROC_ZERO_ROWS:
6035     *flg = mat->nooffproczerorows;
6036     break;
6037   case MAT_SYMMETRIC:
6038     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6039     break;
6040   case MAT_HERMITIAN:
6041     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6042     break;
6043   case MAT_STRUCTURALLY_SYMMETRIC:
6044     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6045     break;
6046   case MAT_SPD:
6047     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6048     break;
6049   case MAT_SYMMETRY_ETERNAL:
6050     *flg = mat->symmetry_eternal;
6051     break;
6052   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6053     *flg = mat->symmetry_eternal;
6054     break;
6055   default:
6056     break;
6057   }
6058   PetscFunctionReturn(PETSC_SUCCESS);
6059 }
6060 
6061 /*@
6062   MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6063   this routine retains the old nonzero structure.
6064 
6065   Logically Collective
6066 
6067   Input Parameter:
6068 . mat - the matrix
6069 
6070   Level: intermediate
6071 
6072   Note:
6073   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.
6074   See the Performance chapter of the users manual for information on preallocating matrices.
6075 
6076 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6077 @*/
6078 PetscErrorCode MatZeroEntries(Mat mat)
6079 {
6080   PetscFunctionBegin;
6081   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6082   PetscValidType(mat, 1);
6083   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6084   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");
6085   MatCheckPreallocated(mat, 1);
6086 
6087   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6088   PetscUseTypeMethod(mat, zeroentries);
6089   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6090   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6091   PetscFunctionReturn(PETSC_SUCCESS);
6092 }
6093 
6094 /*@
6095   MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6096   of a set of rows and columns of a matrix.
6097 
6098   Collective
6099 
6100   Input Parameters:
6101 + mat     - the matrix
6102 . numRows - the number of rows/columns to zero
6103 . rows    - the global row indices
6104 . diag    - value put in the diagonal of the eliminated rows
6105 . x       - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6106 - b       - optional vector of the right hand side, that will be adjusted by provided solution entries
6107 
6108   Level: intermediate
6109 
6110   Notes:
6111   This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6112 
6113   For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6114   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
6115 
6116   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6117   Krylov method to take advantage of the known solution on the zeroed rows.
6118 
6119   For the parallel case, all processes that share the matrix (i.e.,
6120   those in the communicator used for matrix creation) MUST call this
6121   routine, regardless of whether any rows being zeroed are owned by
6122   them.
6123 
6124   Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6125 
6126   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6127   list only rows local to itself).
6128 
6129   The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6130 
6131 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6132           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6133 @*/
6134 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6135 {
6136   PetscFunctionBegin;
6137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6138   PetscValidType(mat, 1);
6139   if (numRows) PetscValidIntPointer(rows, 3);
6140   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6141   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6142   MatCheckPreallocated(mat, 1);
6143 
6144   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6145   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6146   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6147   PetscFunctionReturn(PETSC_SUCCESS);
6148 }
6149 
6150 /*@
6151   MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6152   of a set of rows and columns of a matrix.
6153 
6154   Collective
6155 
6156   Input Parameters:
6157 + mat  - the matrix
6158 . is   - the rows to zero
6159 . diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6160 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6161 - b    - optional vector of right hand side, that will be adjusted by provided solution
6162 
6163   Level: intermediate
6164 
6165   Note:
6166   See `MatZeroRowsColumns()` for details on how this routine operates.
6167 
6168 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6169           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6170 @*/
6171 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6172 {
6173   PetscInt        numRows;
6174   const PetscInt *rows;
6175 
6176   PetscFunctionBegin;
6177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6178   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6179   PetscValidType(mat, 1);
6180   PetscValidType(is, 2);
6181   PetscCall(ISGetLocalSize(is, &numRows));
6182   PetscCall(ISGetIndices(is, &rows));
6183   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6184   PetscCall(ISRestoreIndices(is, &rows));
6185   PetscFunctionReturn(PETSC_SUCCESS);
6186 }
6187 
6188 /*@
6189   MatZeroRows - Zeros all entries (except possibly the main diagonal)
6190   of a set of rows of a matrix.
6191 
6192   Collective
6193 
6194   Input Parameters:
6195 + mat     - the matrix
6196 . numRows - the number of rows to zero
6197 . rows    - the global row indices
6198 . diag    - value put in the diagonal of the zeroed rows
6199 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6200 - b       - optional vector of right hand side, that will be adjusted by provided solution entries
6201 
6202   Level: intermediate
6203 
6204   Notes:
6205   This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6206 
6207   For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6208 
6209   If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6210   Krylov method to take advantage of the known solution on the zeroed rows.
6211 
6212   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)
6213   from the matrix.
6214 
6215   Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6216   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
6217   formats this does not alter the nonzero structure.
6218 
6219   If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6220   of the matrix is not changed the values are
6221   merely zeroed.
6222 
6223   The user can set a value in the diagonal entry (or for the `MATAIJ` format
6224   formats can optionally remove the main diagonal entry from the
6225   nonzero structure as well, by passing 0.0 as the final argument).
6226 
6227   For the parallel case, all processes that share the matrix (i.e.,
6228   those in the communicator used for matrix creation) MUST call this
6229   routine, regardless of whether any rows being zeroed are owned by
6230   them.
6231 
6232   Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6233   list only rows local to itself).
6234 
6235   You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6236   owns that are to be zeroed. This saves a global synchronization in the implementation.
6237 
6238 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6239           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6240 @*/
6241 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6242 {
6243   PetscFunctionBegin;
6244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6245   PetscValidType(mat, 1);
6246   if (numRows) PetscValidIntPointer(rows, 3);
6247   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6248   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6249   MatCheckPreallocated(mat, 1);
6250 
6251   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6252   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6253   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6254   PetscFunctionReturn(PETSC_SUCCESS);
6255 }
6256 
6257 /*@
6258   MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6259   of a set of rows of a matrix.
6260 
6261   Collective
6262 
6263   Input Parameters:
6264 + mat  - the matrix
6265 . is   - index set of rows to remove (if `NULL` then no row is removed)
6266 . diag - value put in all diagonals of eliminated rows
6267 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6268 - b    - optional vector of right hand side, that will be adjusted by provided solution
6269 
6270   Level: intermediate
6271 
6272   Note:
6273   See `MatZeroRows()` for details on how this routine operates.
6274 
6275 .seealso: [](ch_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6276           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6277 @*/
6278 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6279 {
6280   PetscInt        numRows = 0;
6281   const PetscInt *rows    = NULL;
6282 
6283   PetscFunctionBegin;
6284   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6285   PetscValidType(mat, 1);
6286   if (is) {
6287     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6288     PetscCall(ISGetLocalSize(is, &numRows));
6289     PetscCall(ISGetIndices(is, &rows));
6290   }
6291   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6292   if (is) PetscCall(ISRestoreIndices(is, &rows));
6293   PetscFunctionReturn(PETSC_SUCCESS);
6294 }
6295 
6296 /*@
6297   MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6298   of a set of rows of a matrix. These rows must be local to the process.
6299 
6300   Collective
6301 
6302   Input Parameters:
6303 + mat     - the matrix
6304 . numRows - the number of rows to remove
6305 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6306 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6307 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6308 - b       - optional vector of right hand side, that will be adjusted by provided solution
6309 
6310   Level: intermediate
6311 
6312   Notes:
6313   See `MatZeroRows()` for details on how this routine operates.
6314 
6315   The grid coordinates are across the entire grid, not just the local portion
6316 
6317   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6318   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6319   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6320   `DM_BOUNDARY_PERIODIC` boundary type.
6321 
6322   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
6323   a single value per point) you can skip filling those indices.
6324 
6325   Fortran Notes:
6326   `idxm` and `idxn` should be declared as
6327 $     MatStencil idxm(4, m)
6328   and the values inserted using
6329 .vb
6330     idxm(MatStencil_i, 1) = i
6331     idxm(MatStencil_j, 1) = j
6332     idxm(MatStencil_k, 1) = k
6333     idxm(MatStencil_c, 1) = c
6334    etc
6335 .ve
6336 
6337 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6338           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6339 @*/
6340 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6341 {
6342   PetscInt  dim    = mat->stencil.dim;
6343   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6344   PetscInt *dims   = mat->stencil.dims + 1;
6345   PetscInt *starts = mat->stencil.starts;
6346   PetscInt *dxm    = (PetscInt *)rows;
6347   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6348 
6349   PetscFunctionBegin;
6350   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6351   PetscValidType(mat, 1);
6352   if (numRows) PetscValidPointer(rows, 3);
6353 
6354   PetscCall(PetscMalloc1(numRows, &jdxm));
6355   for (i = 0; i < numRows; ++i) {
6356     /* Skip unused dimensions (they are ordered k, j, i, c) */
6357     for (j = 0; j < 3 - sdim; ++j) dxm++;
6358     /* Local index in X dir */
6359     tmp = *dxm++ - starts[0];
6360     /* Loop over remaining dimensions */
6361     for (j = 0; j < dim - 1; ++j) {
6362       /* If nonlocal, set index to be negative */
6363       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6364       /* Update local index */
6365       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6366     }
6367     /* Skip component slot if necessary */
6368     if (mat->stencil.noc) dxm++;
6369     /* Local row number */
6370     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6371   }
6372   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6373   PetscCall(PetscFree(jdxm));
6374   PetscFunctionReturn(PETSC_SUCCESS);
6375 }
6376 
6377 /*@
6378   MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6379   of a set of rows and columns of a matrix.
6380 
6381   Collective
6382 
6383   Input Parameters:
6384 + mat     - the matrix
6385 . numRows - the number of rows/columns to remove
6386 . rows    - the grid coordinates (and component number when dof > 1) for matrix rows
6387 . diag    - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6388 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6389 - b       - optional vector of right hand side, that will be adjusted by provided solution
6390 
6391   Level: intermediate
6392 
6393   Notes:
6394   See `MatZeroRowsColumns()` for details on how this routine operates.
6395 
6396   The grid coordinates are across the entire grid, not just the local portion
6397 
6398   For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6399   obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6400   etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6401   `DM_BOUNDARY_PERIODIC` boundary type.
6402 
6403   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
6404   a single value per point) you can skip filling those indices.
6405 
6406   Fortran Notes:
6407   `idxm` and `idxn` should be declared as
6408 $     MatStencil idxm(4, m)
6409   and the values inserted using
6410 .vb
6411     idxm(MatStencil_i, 1) = i
6412     idxm(MatStencil_j, 1) = j
6413     idxm(MatStencil_k, 1) = k
6414     idxm(MatStencil_c, 1) = c
6415     etc
6416 .ve
6417 
6418 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6419           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6420 @*/
6421 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6422 {
6423   PetscInt  dim    = mat->stencil.dim;
6424   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6425   PetscInt *dims   = mat->stencil.dims + 1;
6426   PetscInt *starts = mat->stencil.starts;
6427   PetscInt *dxm    = (PetscInt *)rows;
6428   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6429 
6430   PetscFunctionBegin;
6431   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6432   PetscValidType(mat, 1);
6433   if (numRows) PetscValidPointer(rows, 3);
6434 
6435   PetscCall(PetscMalloc1(numRows, &jdxm));
6436   for (i = 0; i < numRows; ++i) {
6437     /* Skip unused dimensions (they are ordered k, j, i, c) */
6438     for (j = 0; j < 3 - sdim; ++j) dxm++;
6439     /* Local index in X dir */
6440     tmp = *dxm++ - starts[0];
6441     /* Loop over remaining dimensions */
6442     for (j = 0; j < dim - 1; ++j) {
6443       /* If nonlocal, set index to be negative */
6444       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6445       /* Update local index */
6446       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6447     }
6448     /* Skip component slot if necessary */
6449     if (mat->stencil.noc) dxm++;
6450     /* Local row number */
6451     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6452   }
6453   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6454   PetscCall(PetscFree(jdxm));
6455   PetscFunctionReturn(PETSC_SUCCESS);
6456 }
6457 
6458 /*@C
6459   MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6460   of a set of rows of a matrix; using local numbering of rows.
6461 
6462   Collective
6463 
6464   Input Parameters:
6465 + mat     - the matrix
6466 . numRows - the number of rows to remove
6467 . rows    - the local row indices
6468 . diag    - value put in all diagonals of eliminated rows
6469 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6470 - b       - optional vector of right hand side, that will be adjusted by provided solution
6471 
6472   Level: intermediate
6473 
6474   Notes:
6475   Before calling `MatZeroRowsLocal()`, the user must first set the
6476   local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6477 
6478   See `MatZeroRows()` for details on how this routine operates.
6479 
6480 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6481           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6482 @*/
6483 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6484 {
6485   PetscFunctionBegin;
6486   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6487   PetscValidType(mat, 1);
6488   if (numRows) PetscValidIntPointer(rows, 3);
6489   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6490   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6491   MatCheckPreallocated(mat, 1);
6492 
6493   if (mat->ops->zerorowslocal) {
6494     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6495   } else {
6496     IS              is, newis;
6497     const PetscInt *newRows;
6498 
6499     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6500     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6501     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6502     PetscCall(ISGetIndices(newis, &newRows));
6503     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6504     PetscCall(ISRestoreIndices(newis, &newRows));
6505     PetscCall(ISDestroy(&newis));
6506     PetscCall(ISDestroy(&is));
6507   }
6508   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6509   PetscFunctionReturn(PETSC_SUCCESS);
6510 }
6511 
6512 /*@
6513   MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6514   of a set of rows of a matrix; using local numbering of rows.
6515 
6516   Collective
6517 
6518   Input Parameters:
6519 + mat  - the matrix
6520 . is   - index set of rows to remove
6521 . diag - value put in all diagonals of eliminated rows
6522 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6523 - b    - optional vector of right hand side, that will be adjusted by provided solution
6524 
6525   Level: intermediate
6526 
6527   Notes:
6528   Before calling `MatZeroRowsLocalIS()`, the user must first set the
6529   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6530 
6531   See `MatZeroRows()` for details on how this routine operates.
6532 
6533 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6534           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6535 @*/
6536 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6537 {
6538   PetscInt        numRows;
6539   const PetscInt *rows;
6540 
6541   PetscFunctionBegin;
6542   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6543   PetscValidType(mat, 1);
6544   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6545   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6546   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6547   MatCheckPreallocated(mat, 1);
6548 
6549   PetscCall(ISGetLocalSize(is, &numRows));
6550   PetscCall(ISGetIndices(is, &rows));
6551   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6552   PetscCall(ISRestoreIndices(is, &rows));
6553   PetscFunctionReturn(PETSC_SUCCESS);
6554 }
6555 
6556 /*@
6557   MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6558   of a set of rows and columns of a matrix; using local numbering of rows.
6559 
6560   Collective
6561 
6562   Input Parameters:
6563 + mat     - the matrix
6564 . numRows - the number of rows to remove
6565 . rows    - the global row indices
6566 . diag    - value put in all diagonals of eliminated rows
6567 . x       - optional vector of solutions for zeroed rows (other entries in vector are not used)
6568 - b       - optional vector of right hand side, that will be adjusted by provided solution
6569 
6570   Level: intermediate
6571 
6572   Notes:
6573   Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6574   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6575 
6576   See `MatZeroRowsColumns()` for details on how this routine operates.
6577 
6578 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6579           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6580 @*/
6581 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6582 {
6583   IS              is, newis;
6584   const PetscInt *newRows;
6585 
6586   PetscFunctionBegin;
6587   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6588   PetscValidType(mat, 1);
6589   if (numRows) PetscValidIntPointer(rows, 3);
6590   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6591   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6592   MatCheckPreallocated(mat, 1);
6593 
6594   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6595   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6596   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6597   PetscCall(ISGetIndices(newis, &newRows));
6598   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6599   PetscCall(ISRestoreIndices(newis, &newRows));
6600   PetscCall(ISDestroy(&newis));
6601   PetscCall(ISDestroy(&is));
6602   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6603   PetscFunctionReturn(PETSC_SUCCESS);
6604 }
6605 
6606 /*@
6607   MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6608   of a set of rows and columns of a matrix; using local numbering of rows.
6609 
6610   Collective
6611 
6612   Input Parameters:
6613 + mat  - the matrix
6614 . is   - index set of rows to remove
6615 . diag - value put in all diagonals of eliminated rows
6616 . x    - optional vector of solutions for zeroed rows (other entries in vector are not used)
6617 - b    - optional vector of right hand side, that will be adjusted by provided solution
6618 
6619   Level: intermediate
6620 
6621   Notes:
6622   Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6623   local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6624 
6625   See `MatZeroRowsColumns()` for details on how this routine operates.
6626 
6627 .seealso: [](ch_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6628           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6629 @*/
6630 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6631 {
6632   PetscInt        numRows;
6633   const PetscInt *rows;
6634 
6635   PetscFunctionBegin;
6636   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6637   PetscValidType(mat, 1);
6638   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6639   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6640   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6641   MatCheckPreallocated(mat, 1);
6642 
6643   PetscCall(ISGetLocalSize(is, &numRows));
6644   PetscCall(ISGetIndices(is, &rows));
6645   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6646   PetscCall(ISRestoreIndices(is, &rows));
6647   PetscFunctionReturn(PETSC_SUCCESS);
6648 }
6649 
6650 /*@C
6651   MatGetSize - Returns the numbers of rows and columns in a matrix.
6652 
6653   Not Collective
6654 
6655   Input Parameter:
6656 . mat - the matrix
6657 
6658   Output Parameters:
6659 + m - the number of global rows
6660 - n - the number of global columns
6661 
6662   Level: beginner
6663 
6664   Note:
6665   Both output parameters can be `NULL` on input.
6666 
6667 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6668 @*/
6669 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6670 {
6671   PetscFunctionBegin;
6672   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6673   if (m) *m = mat->rmap->N;
6674   if (n) *n = mat->cmap->N;
6675   PetscFunctionReturn(PETSC_SUCCESS);
6676 }
6677 
6678 /*@C
6679   MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6680   of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6681 
6682   Not Collective
6683 
6684   Input Parameter:
6685 . mat - the matrix
6686 
6687   Output Parameters:
6688 + m - the number of local rows, use `NULL` to not obtain this value
6689 - n - the number of local columns, use `NULL` to not obtain this value
6690 
6691   Level: beginner
6692 
6693 .seealso: [](ch_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6694 @*/
6695 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6696 {
6697   PetscFunctionBegin;
6698   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6699   if (m) PetscValidIntPointer(m, 2);
6700   if (n) PetscValidIntPointer(n, 3);
6701   if (m) *m = mat->rmap->n;
6702   if (n) *n = mat->cmap->n;
6703   PetscFunctionReturn(PETSC_SUCCESS);
6704 }
6705 
6706 /*@C
6707   MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6708   this processor. (The columns of the "diagonal block" for most sparse matrix formats). See [Matrix Layouts](sec_matlayout) for details on matrix layouts.
6709 
6710   Not Collective, unless matrix has not been allocated, then collective
6711 
6712   Input Parameter:
6713 . mat - the matrix
6714 
6715   Output Parameters:
6716 + m - the global index of the first local column, use `NULL` to not obtain this value
6717 - n - one more than the global index of the last local column, use `NULL` to not obtain this value
6718 
6719   Level: developer
6720 
6721 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6722 @*/
6723 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6724 {
6725   PetscFunctionBegin;
6726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6727   PetscValidType(mat, 1);
6728   if (m) PetscValidIntPointer(m, 2);
6729   if (n) PetscValidIntPointer(n, 3);
6730   MatCheckPreallocated(mat, 1);
6731   if (m) *m = mat->cmap->rstart;
6732   if (n) *n = mat->cmap->rend;
6733   PetscFunctionReturn(PETSC_SUCCESS);
6734 }
6735 
6736 /*@C
6737   MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6738   this MPI process. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6739   vector product with this matrix. See [Matrix Layouts](sec_matlayout) for details on matrix layouts
6740 
6741   Not Collective
6742 
6743   Input Parameter:
6744 . mat - the matrix
6745 
6746   Output Parameters:
6747 + m - the global index of the first local row, use `NULL` to not obtain this value
6748 - n - one more than the global index of the last local row, use `NULL` to not obtain this value
6749 
6750   Level: beginner
6751 
6752   Note:
6753   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6754   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6755   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6756 
6757 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6758           `PetscLayout`
6759 @*/
6760 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6761 {
6762   PetscFunctionBegin;
6763   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6764   PetscValidType(mat, 1);
6765   if (m) PetscValidIntPointer(m, 2);
6766   if (n) PetscValidIntPointer(n, 3);
6767   MatCheckPreallocated(mat, 1);
6768   if (m) *m = mat->rmap->rstart;
6769   if (n) *n = mat->rmap->rend;
6770   PetscFunctionReturn(PETSC_SUCCESS);
6771 }
6772 
6773 /*@C
6774   MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6775   each process. For all matrices  it returns the ranges of matrix rows associated with rows of a vector that would contain the result of a matrix
6776   vector product with this matrix. See [Matrix Layouts](sec_matlayout) for details on matrix layouts
6777 
6778   Not Collective, unless matrix has not been allocated
6779 
6780   Input Parameter:
6781 . mat - the matrix
6782 
6783   Output Parameter:
6784 . ranges - start of each processors portion plus one more than the total length at the end
6785 
6786   Level: beginner
6787 
6788 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6789 @*/
6790 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6791 {
6792   PetscFunctionBegin;
6793   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6794   PetscValidType(mat, 1);
6795   MatCheckPreallocated(mat, 1);
6796   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6797   PetscFunctionReturn(PETSC_SUCCESS);
6798 }
6799 
6800 /*@C
6801   MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6802   each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See [Matrix Layouts](sec_matlayout) for details on matrix layouts.
6803 
6804   Not Collective, unless matrix has not been allocated
6805 
6806   Input Parameter:
6807 . mat - the matrix
6808 
6809   Output Parameter:
6810 . ranges - start of each processors portion plus one more then the total length at the end
6811 
6812   Level: beginner
6813 
6814 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6815 @*/
6816 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6817 {
6818   PetscFunctionBegin;
6819   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6820   PetscValidType(mat, 1);
6821   MatCheckPreallocated(mat, 1);
6822   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6823   PetscFunctionReturn(PETSC_SUCCESS);
6824 }
6825 
6826 /*@C
6827   MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6828   corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6829   is more complicated. See [Matrix Layouts](sec_matlayout) for details on matrix layouts.
6830 
6831   Not Collective
6832 
6833   Input Parameter:
6834 . A - matrix
6835 
6836   Output Parameters:
6837 + rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6838 - cols - columns in which this process owns elements, use `NULL` to not obtain this value
6839 
6840   Level: intermediate
6841 
6842 .seealso: [](ch_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6843 @*/
6844 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6845 {
6846   PetscErrorCode (*f)(Mat, IS *, IS *);
6847 
6848   PetscFunctionBegin;
6849   MatCheckPreallocated(A, 1);
6850   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6851   if (f) {
6852     PetscCall((*f)(A, rows, cols));
6853   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6854     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6855     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6856   }
6857   PetscFunctionReturn(PETSC_SUCCESS);
6858 }
6859 
6860 /*@C
6861   MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6862   Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6863   to complete the factorization.
6864 
6865   Collective
6866 
6867   Input Parameters:
6868 + fact - the factorized matrix obtained with `MatGetFactor()`
6869 . mat  - the matrix
6870 . row  - row permutation
6871 . col  - column permutation
6872 - info - structure containing
6873 .vb
6874       levels - number of levels of fill.
6875       expected fill - as ratio of original fill.
6876       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6877                 missing diagonal entries)
6878 .ve
6879 
6880   Level: developer
6881 
6882   Notes:
6883   See [Matrix Factorization](sec_matfactor) for additional information.
6884 
6885   Most users should employ the `KSP` interface for linear solvers
6886   instead of working directly with matrix algebra routines such as this.
6887   See, e.g., `KSPCreate()`.
6888 
6889   Uses the definition of level of fill as in Y. Saad, 2003
6890 
6891   Developer Notes:
6892   The Fortran interface is not autogenerated as the
6893   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6894 
6895   References:
6896 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6897 
6898 .seealso: [](ch_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6899           `MatGetOrdering()`, `MatFactorInfo`
6900 @*/
6901 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6902 {
6903   PetscFunctionBegin;
6904   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6905   PetscValidType(mat, 2);
6906   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6907   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6908   PetscValidPointer(info, 5);
6909   PetscValidPointer(fact, 1);
6910   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6911   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6912   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6913   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6914   MatCheckPreallocated(mat, 2);
6915 
6916   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6917   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6918   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6919   PetscFunctionReturn(PETSC_SUCCESS);
6920 }
6921 
6922 /*@C
6923   MatICCFactorSymbolic - Performs symbolic incomplete
6924   Cholesky factorization for a symmetric matrix.  Use
6925   `MatCholeskyFactorNumeric()` to complete the factorization.
6926 
6927   Collective
6928 
6929   Input Parameters:
6930 + fact - the factorized matrix obtained with `MatGetFactor()`
6931 . mat  - the matrix to be factored
6932 . perm - row and column permutation
6933 - info - structure containing
6934 .vb
6935       levels - number of levels of fill.
6936       expected fill - as ratio of original fill.
6937 .ve
6938 
6939   Level: developer
6940 
6941   Notes:
6942   Most users should employ the `KSP` interface for linear solvers
6943   instead of working directly with matrix algebra routines such as this.
6944   See, e.g., `KSPCreate()`.
6945 
6946   This uses the definition of level of fill as in Y. Saad, 2003
6947 
6948   Developer Notes:
6949   The Fortran interface is not autogenerated as the
6950   interface definition cannot be generated correctly [due to `MatFactorInfo`]
6951 
6952   References:
6953 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6954 
6955 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6956 @*/
6957 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6958 {
6959   PetscFunctionBegin;
6960   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6961   PetscValidType(mat, 2);
6962   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6963   PetscValidPointer(info, 4);
6964   PetscValidPointer(fact, 1);
6965   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6966   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6967   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6968   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6969   MatCheckPreallocated(mat, 2);
6970 
6971   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6972   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6973   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6974   PetscFunctionReturn(PETSC_SUCCESS);
6975 }
6976 
6977 /*@C
6978   MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6979   points to an array of valid matrices, they may be reused to store the new
6980   submatrices.
6981 
6982   Collective
6983 
6984   Input Parameters:
6985 + mat   - the matrix
6986 . n     - the number of submatrixes to be extracted (on this processor, may be zero)
6987 . irow  - index set of rows to extract
6988 . icol  - index set of columns to extract
6989 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6990 
6991   Output Parameter:
6992 . submat - the array of submatrices
6993 
6994   Level: advanced
6995 
6996   Notes:
6997   `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6998   (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6999   to extract a parallel submatrix.
7000 
7001   Some matrix types place restrictions on the row and column
7002   indices, such as that they be sorted or that they be equal to each other.
7003 
7004   The index sets may not have duplicate entries.
7005 
7006   When extracting submatrices from a parallel matrix, each processor can
7007   form a different submatrix by setting the rows and columns of its
7008   individual index sets according to the local submatrix desired.
7009 
7010   When finished using the submatrices, the user should destroy
7011   them with `MatDestroySubMatrices()`.
7012 
7013   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
7014   original matrix has not changed from that last call to `MatCreateSubMatrices()`.
7015 
7016   This routine creates the matrices in submat; you should NOT create them before
7017   calling it. It also allocates the array of matrix pointers submat.
7018 
7019   For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7020   request one row/column in a block, they must request all rows/columns that are in
7021   that block. For example, if the block size is 2 you cannot request just row 0 and
7022   column 0.
7023 
7024   Fortran Notes:
7025   The Fortran interface is slightly different from that given below; it
7026   requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7027 
7028 .seealso: [](ch_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7029 @*/
7030 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7031 {
7032   PetscInt  i;
7033   PetscBool eq;
7034 
7035   PetscFunctionBegin;
7036   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7037   PetscValidType(mat, 1);
7038   if (n) {
7039     PetscValidPointer(irow, 3);
7040     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7041     PetscValidPointer(icol, 4);
7042     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7043   }
7044   PetscValidPointer(submat, 6);
7045   if (n && scall == MAT_REUSE_MATRIX) {
7046     PetscValidPointer(*submat, 6);
7047     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7048   }
7049   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7050   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7051   MatCheckPreallocated(mat, 1);
7052   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7053   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7054   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7055   for (i = 0; i < n; i++) {
7056     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7057     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7058     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7059 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7060     if (mat->boundtocpu && mat->bindingpropagates) {
7061       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7062       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7063     }
7064 #endif
7065   }
7066   PetscFunctionReturn(PETSC_SUCCESS);
7067 }
7068 
7069 /*@C
7070   MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7071 
7072   Collective
7073 
7074   Input Parameters:
7075 + mat   - the matrix
7076 . n     - the number of submatrixes to be extracted
7077 . irow  - index set of rows to extract
7078 . icol  - index set of columns to extract
7079 - scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7080 
7081   Output Parameter:
7082 . submat - the array of submatrices
7083 
7084   Level: advanced
7085 
7086   Note:
7087   This is used by `PCGASM`
7088 
7089 .seealso: [](ch_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7090 @*/
7091 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7092 {
7093   PetscInt  i;
7094   PetscBool eq;
7095 
7096   PetscFunctionBegin;
7097   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7098   PetscValidType(mat, 1);
7099   if (n) {
7100     PetscValidPointer(irow, 3);
7101     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7102     PetscValidPointer(icol, 4);
7103     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7104   }
7105   PetscValidPointer(submat, 6);
7106   if (n && scall == MAT_REUSE_MATRIX) {
7107     PetscValidPointer(*submat, 6);
7108     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7109   }
7110   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7111   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7112   MatCheckPreallocated(mat, 1);
7113 
7114   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7115   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7116   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7117   for (i = 0; i < n; i++) {
7118     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7119     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7120   }
7121   PetscFunctionReturn(PETSC_SUCCESS);
7122 }
7123 
7124 /*@C
7125   MatDestroyMatrices - Destroys an array of matrices.
7126 
7127   Collective
7128 
7129   Input Parameters:
7130 + n   - the number of local matrices
7131 - mat - the matrices (this is a pointer to the array of matrices)
7132 
7133   Level: advanced
7134 
7135   Note:
7136   Frees not only the matrices, but also the array that contains the matrices
7137 
7138   Fortran Notes:
7139   This does not free the array.
7140 
7141 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7142 @*/
7143 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7144 {
7145   PetscInt i;
7146 
7147   PetscFunctionBegin;
7148   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7149   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7150   PetscValidPointer(mat, 2);
7151 
7152   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7153 
7154   /* memory is allocated even if n = 0 */
7155   PetscCall(PetscFree(*mat));
7156   PetscFunctionReturn(PETSC_SUCCESS);
7157 }
7158 
7159 /*@C
7160   MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7161 
7162   Collective
7163 
7164   Input Parameters:
7165 + n   - the number of local matrices
7166 - mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7167                        sequence of `MatCreateSubMatrices()`)
7168 
7169   Level: advanced
7170 
7171   Note:
7172   Frees not only the matrices, but also the array that contains the matrices
7173 
7174   Fortran Notes:
7175   This does not free the array.
7176 
7177 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7178 @*/
7179 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7180 {
7181   Mat mat0;
7182 
7183   PetscFunctionBegin;
7184   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7185   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7186   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7187   PetscValidPointer(mat, 2);
7188 
7189   mat0 = (*mat)[0];
7190   if (mat0 && mat0->ops->destroysubmatrices) {
7191     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7192   } else {
7193     PetscCall(MatDestroyMatrices(n, mat));
7194   }
7195   PetscFunctionReturn(PETSC_SUCCESS);
7196 }
7197 
7198 /*@C
7199   MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7200 
7201   Collective
7202 
7203   Input Parameter:
7204 . mat - the matrix
7205 
7206   Output Parameter:
7207 . matstruct - the sequential matrix with the nonzero structure of mat
7208 
7209   Level: developer
7210 
7211 .seealso: [](ch_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7212 @*/
7213 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7214 {
7215   PetscFunctionBegin;
7216   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7217   PetscValidPointer(matstruct, 2);
7218 
7219   PetscValidType(mat, 1);
7220   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7221   MatCheckPreallocated(mat, 1);
7222 
7223   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7224   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7225   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7226   PetscFunctionReturn(PETSC_SUCCESS);
7227 }
7228 
7229 /*@C
7230   MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7231 
7232   Collective
7233 
7234   Input Parameter:
7235 . mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7236                        sequence of `MatGetSeqNonzeroStructure()`)
7237 
7238   Level: advanced
7239 
7240   Note:
7241   Frees not only the matrices, but also the array that contains the matrices
7242 
7243 .seealso: [](ch_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7244 @*/
7245 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7246 {
7247   PetscFunctionBegin;
7248   PetscValidPointer(mat, 1);
7249   PetscCall(MatDestroy(mat));
7250   PetscFunctionReturn(PETSC_SUCCESS);
7251 }
7252 
7253 /*@
7254   MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7255   replaces the index sets by larger ones that represent submatrices with
7256   additional overlap.
7257 
7258   Collective
7259 
7260   Input Parameters:
7261 + mat - the matrix
7262 . n   - the number of index sets
7263 . is  - the array of index sets (these index sets will changed during the call)
7264 - ov  - the additional overlap requested
7265 
7266   Options Database Key:
7267 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7268 
7269   Level: developer
7270 
7271   Note:
7272   The computed overlap preserves the matrix block sizes when the blocks are square.
7273   That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7274   that block are included in the overlap regardless of whether each specific column would increase the overlap.
7275 
7276 .seealso: [](ch_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7277 @*/
7278 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7279 {
7280   PetscInt i, bs, cbs;
7281 
7282   PetscFunctionBegin;
7283   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7284   PetscValidType(mat, 1);
7285   PetscValidLogicalCollectiveInt(mat, n, 2);
7286   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7287   if (n) {
7288     PetscValidPointer(is, 3);
7289     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7290   }
7291   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7292   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7293   MatCheckPreallocated(mat, 1);
7294 
7295   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7296   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7297   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7298   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7299   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7300   if (bs == cbs) {
7301     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7302   }
7303   PetscFunctionReturn(PETSC_SUCCESS);
7304 }
7305 
7306 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7307 
7308 /*@
7309   MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7310   a sub communicator, replaces the index sets by larger ones that represent submatrices with
7311   additional overlap.
7312 
7313   Collective
7314 
7315   Input Parameters:
7316 + mat - the matrix
7317 . n   - the number of index sets
7318 . is  - the array of index sets (these index sets will changed during the call)
7319 - ov  - the additional overlap requested
7320 
7321   `   Options Database Key:
7322 . -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7323 
7324   Level: developer
7325 
7326 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7327 @*/
7328 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7329 {
7330   PetscInt i;
7331 
7332   PetscFunctionBegin;
7333   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7334   PetscValidType(mat, 1);
7335   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7336   if (n) {
7337     PetscValidPointer(is, 3);
7338     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7339   }
7340   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7341   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7342   MatCheckPreallocated(mat, 1);
7343   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7344   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7345   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7346   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7347   PetscFunctionReturn(PETSC_SUCCESS);
7348 }
7349 
7350 /*@
7351   MatGetBlockSize - Returns the matrix block size.
7352 
7353   Not Collective
7354 
7355   Input Parameter:
7356 . mat - the matrix
7357 
7358   Output Parameter:
7359 . bs - block size
7360 
7361   Level: intermediate
7362 
7363   Notes:
7364   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7365 
7366   If the block size has not been set yet this routine returns 1.
7367 
7368 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7369 @*/
7370 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7371 {
7372   PetscFunctionBegin;
7373   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7374   PetscValidIntPointer(bs, 2);
7375   *bs = PetscAbs(mat->rmap->bs);
7376   PetscFunctionReturn(PETSC_SUCCESS);
7377 }
7378 
7379 /*@
7380   MatGetBlockSizes - Returns the matrix block row and column sizes.
7381 
7382   Not Collective
7383 
7384   Input Parameter:
7385 . mat - the matrix
7386 
7387   Output Parameters:
7388 + rbs - row block size
7389 - cbs - column block size
7390 
7391   Level: intermediate
7392 
7393   Notes:
7394   Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7395   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7396 
7397   If a block size has not been set yet this routine returns 1.
7398 
7399 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7400 @*/
7401 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7402 {
7403   PetscFunctionBegin;
7404   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7405   if (rbs) PetscValidIntPointer(rbs, 2);
7406   if (cbs) PetscValidIntPointer(cbs, 3);
7407   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7408   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7409   PetscFunctionReturn(PETSC_SUCCESS);
7410 }
7411 
7412 /*@
7413   MatSetBlockSize - Sets the matrix block size.
7414 
7415   Logically Collective
7416 
7417   Input Parameters:
7418 + mat - the matrix
7419 - bs  - block size
7420 
7421   Level: intermediate
7422 
7423   Notes:
7424   Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7425   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7426 
7427   For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7428   is compatible with the matrix local sizes.
7429 
7430 .seealso: [](ch_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7431 @*/
7432 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7433 {
7434   PetscFunctionBegin;
7435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7436   PetscValidLogicalCollectiveInt(mat, bs, 2);
7437   PetscCall(MatSetBlockSizes(mat, bs, bs));
7438   PetscFunctionReturn(PETSC_SUCCESS);
7439 }
7440 
7441 typedef struct {
7442   PetscInt         n;
7443   IS              *is;
7444   Mat             *mat;
7445   PetscObjectState nonzerostate;
7446   Mat              C;
7447 } EnvelopeData;
7448 
7449 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7450 {
7451   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7452   PetscCall(PetscFree(edata->is));
7453   PetscCall(PetscFree(edata));
7454   return PETSC_SUCCESS;
7455 }
7456 
7457 /*
7458    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7459          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7460 
7461    Collective
7462 
7463    Input Parameter:
7464 .  mat - the matrix
7465 
7466    Notes:
7467      There can be zeros within the blocks
7468 
7469      The blocks can overlap between processes, including laying on more than two processes
7470 
7471 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7472 */
7473 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7474 {
7475   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7476   PetscInt          *diag, *odiag, sc;
7477   VecScatter         scatter;
7478   PetscScalar       *seqv;
7479   const PetscScalar *parv;
7480   const PetscInt    *ia, *ja;
7481   PetscBool          set, flag, done;
7482   Mat                AA = mat, A;
7483   MPI_Comm           comm;
7484   PetscMPIInt        rank, size, tag;
7485   MPI_Status         status;
7486   PetscContainer     container;
7487   EnvelopeData      *edata;
7488   Vec                seq, par;
7489   IS                 isglobal;
7490 
7491   PetscFunctionBegin;
7492   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7493   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7494   if (!set || !flag) {
7495     /* TOO: only needs nonzero structure of transpose */
7496     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7497     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7498   }
7499   PetscCall(MatAIJGetLocalMat(AA, &A));
7500   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7501   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7502 
7503   PetscCall(MatGetLocalSize(mat, &n, NULL));
7504   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7505   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7506   PetscCallMPI(MPI_Comm_size(comm, &size));
7507   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7508 
7509   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7510 
7511   if (rank > 0) {
7512     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7513     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7514   }
7515   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7516   for (i = 0; i < n; i++) {
7517     env = PetscMax(env, ja[ia[i + 1] - 1]);
7518     II  = rstart + i;
7519     if (env == II) {
7520       starts[lblocks]  = tbs;
7521       sizes[lblocks++] = 1 + II - tbs;
7522       tbs              = 1 + II;
7523     }
7524   }
7525   if (rank < size - 1) {
7526     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7527     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7528   }
7529 
7530   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7531   if (!set || !flag) PetscCall(MatDestroy(&AA));
7532   PetscCall(MatDestroy(&A));
7533 
7534   PetscCall(PetscNew(&edata));
7535   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7536   edata->n = lblocks;
7537   /* create IS needed for extracting blocks from the original matrix */
7538   PetscCall(PetscMalloc1(lblocks, &edata->is));
7539   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7540 
7541   /* Create the resulting inverse matrix structure with preallocation information */
7542   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7543   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7544   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7545   PetscCall(MatSetType(edata->C, MATAIJ));
7546 
7547   /* Communicate the start and end of each row, from each block to the correct rank */
7548   /* TODO: Use PetscSF instead of VecScatter */
7549   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7550   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7551   PetscCall(VecGetArrayWrite(seq, &seqv));
7552   for (PetscInt i = 0; i < lblocks; i++) {
7553     for (PetscInt j = 0; j < sizes[i]; j++) {
7554       seqv[cnt]     = starts[i];
7555       seqv[cnt + 1] = starts[i] + sizes[i];
7556       cnt += 2;
7557     }
7558   }
7559   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7560   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7561   sc -= cnt;
7562   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7563   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7564   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7565   PetscCall(ISDestroy(&isglobal));
7566   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7567   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7568   PetscCall(VecScatterDestroy(&scatter));
7569   PetscCall(VecDestroy(&seq));
7570   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7571   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7572   PetscCall(VecGetArrayRead(par, &parv));
7573   cnt = 0;
7574   PetscCall(MatGetSize(mat, NULL, &n));
7575   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7576     PetscInt start, end, d = 0, od = 0;
7577 
7578     start = (PetscInt)PetscRealPart(parv[cnt]);
7579     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7580     cnt += 2;
7581 
7582     if (start < cstart) {
7583       od += cstart - start + n - cend;
7584       d += cend - cstart;
7585     } else if (start < cend) {
7586       od += n - cend;
7587       d += cend - start;
7588     } else od += n - start;
7589     if (end <= cstart) {
7590       od -= cstart - end + n - cend;
7591       d -= cend - cstart;
7592     } else if (end < cend) {
7593       od -= n - cend;
7594       d -= cend - end;
7595     } else od -= n - end;
7596 
7597     odiag[i] = od;
7598     diag[i]  = d;
7599   }
7600   PetscCall(VecRestoreArrayRead(par, &parv));
7601   PetscCall(VecDestroy(&par));
7602   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7603   PetscCall(PetscFree2(diag, odiag));
7604   PetscCall(PetscFree2(sizes, starts));
7605 
7606   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7607   PetscCall(PetscContainerSetPointer(container, edata));
7608   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7609   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7610   PetscCall(PetscObjectDereference((PetscObject)container));
7611   PetscFunctionReturn(PETSC_SUCCESS);
7612 }
7613 
7614 /*@
7615   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7616 
7617   Collective
7618 
7619   Input Parameters:
7620 + A     - the matrix
7621 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7622 
7623   Output Parameter:
7624 . C - matrix with inverted block diagonal of `A`
7625 
7626   Level: advanced
7627 
7628   Note:
7629   For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7630 
7631 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7632 @*/
7633 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7634 {
7635   PetscContainer   container;
7636   EnvelopeData    *edata;
7637   PetscObjectState nonzerostate;
7638 
7639   PetscFunctionBegin;
7640   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7641   if (!container) {
7642     PetscCall(MatComputeVariableBlockEnvelope(A));
7643     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7644   }
7645   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7646   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7647   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7648   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7649 
7650   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7651   *C = edata->C;
7652 
7653   for (PetscInt i = 0; i < edata->n; i++) {
7654     Mat          D;
7655     PetscScalar *dvalues;
7656 
7657     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7658     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7659     PetscCall(MatSeqDenseInvert(D));
7660     PetscCall(MatDenseGetArray(D, &dvalues));
7661     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7662     PetscCall(MatDestroy(&D));
7663   }
7664   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7665   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7666   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7667   PetscFunctionReturn(PETSC_SUCCESS);
7668 }
7669 
7670 /*@
7671   MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7672 
7673   Logically Collective
7674 
7675   Input Parameters:
7676 + mat     - the matrix
7677 . nblocks - the number of blocks on this process, each block can only exist on a single process
7678 - bsizes  - the block sizes
7679 
7680   Level: intermediate
7681 
7682   Notes:
7683   Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7684 
7685   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.
7686 
7687 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7688           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7689 @*/
7690 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7691 {
7692   PetscInt i, ncnt = 0, nlocal;
7693 
7694   PetscFunctionBegin;
7695   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7696   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7697   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7698   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7699   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);
7700   PetscCall(PetscFree(mat->bsizes));
7701   mat->nblocks = nblocks;
7702   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7703   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7704   PetscFunctionReturn(PETSC_SUCCESS);
7705 }
7706 
7707 /*@C
7708   MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7709 
7710   Logically Collective; No Fortran Support
7711 
7712   Input Parameter:
7713 . mat - the matrix
7714 
7715   Output Parameters:
7716 + nblocks - the number of blocks on this process
7717 - bsizes  - the block sizes
7718 
7719   Level: intermediate
7720 
7721 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7722 @*/
7723 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7724 {
7725   PetscFunctionBegin;
7726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7727   *nblocks = mat->nblocks;
7728   *bsizes  = mat->bsizes;
7729   PetscFunctionReturn(PETSC_SUCCESS);
7730 }
7731 
7732 /*@
7733   MatSetBlockSizes - Sets the matrix block row and column sizes.
7734 
7735   Logically Collective
7736 
7737   Input Parameters:
7738 + mat - the matrix
7739 . rbs - row block size
7740 - cbs - column block size
7741 
7742   Level: intermediate
7743 
7744   Notes:
7745   Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7746   If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7747   This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7748 
7749   For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7750   are compatible with the matrix local sizes.
7751 
7752   The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7753 
7754 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7755 @*/
7756 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7757 {
7758   PetscFunctionBegin;
7759   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7760   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7761   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7762   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7763   if (mat->rmap->refcnt) {
7764     ISLocalToGlobalMapping l2g  = NULL;
7765     PetscLayout            nmap = NULL;
7766 
7767     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7768     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7769     PetscCall(PetscLayoutDestroy(&mat->rmap));
7770     mat->rmap          = nmap;
7771     mat->rmap->mapping = l2g;
7772   }
7773   if (mat->cmap->refcnt) {
7774     ISLocalToGlobalMapping l2g  = NULL;
7775     PetscLayout            nmap = NULL;
7776 
7777     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7778     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7779     PetscCall(PetscLayoutDestroy(&mat->cmap));
7780     mat->cmap          = nmap;
7781     mat->cmap->mapping = l2g;
7782   }
7783   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7784   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7785   PetscFunctionReturn(PETSC_SUCCESS);
7786 }
7787 
7788 /*@
7789   MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7790 
7791   Logically Collective
7792 
7793   Input Parameters:
7794 + mat     - the matrix
7795 . fromRow - matrix from which to copy row block size
7796 - fromCol - matrix from which to copy column block size (can be same as fromRow)
7797 
7798   Level: developer
7799 
7800 .seealso: [](ch_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7801 @*/
7802 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7803 {
7804   PetscFunctionBegin;
7805   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7806   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7807   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7808   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7809   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7810   PetscFunctionReturn(PETSC_SUCCESS);
7811 }
7812 
7813 /*@
7814   MatResidual - Default routine to calculate the residual r = b - Ax
7815 
7816   Collective
7817 
7818   Input Parameters:
7819 + mat - the matrix
7820 . b   - the right-hand-side
7821 - x   - the approximate solution
7822 
7823   Output Parameter:
7824 . r - location to store the residual
7825 
7826   Level: developer
7827 
7828 .seealso: [](ch_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7829 @*/
7830 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7831 {
7832   PetscFunctionBegin;
7833   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7834   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7835   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7836   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7837   PetscValidType(mat, 1);
7838   MatCheckPreallocated(mat, 1);
7839   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7840   if (!mat->ops->residual) {
7841     PetscCall(MatMult(mat, x, r));
7842     PetscCall(VecAYPX(r, -1.0, b));
7843   } else {
7844     PetscUseTypeMethod(mat, residual, b, x, r);
7845   }
7846   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7847   PetscFunctionReturn(PETSC_SUCCESS);
7848 }
7849 
7850 /*MC
7851     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7852 
7853     Synopsis:
7854     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7855 
7856     Not Collective
7857 
7858     Input Parameters:
7859 +   A - the matrix
7860 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7861 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7862 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7863                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7864                  always used.
7865 
7866     Output Parameters:
7867 +   n - number of local rows in the (possibly compressed) matrix
7868 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7869 .   ja - the column indices
7870 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7871            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7872 
7873     Level: developer
7874 
7875     Note:
7876     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7877 
7878 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7879 M*/
7880 
7881 /*MC
7882     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7883 
7884     Synopsis:
7885     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7886 
7887     Not Collective
7888 
7889     Input Parameters:
7890 +   A - the  matrix
7891 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7892 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7893     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7894                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7895                  always used.
7896 .   n - number of local rows in the (possibly compressed) matrix
7897 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7898 .   ja - the column indices
7899 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7900            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7901 
7902     Level: developer
7903 
7904 .seealso: [](ch_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7905 M*/
7906 
7907 /*@C
7908   MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7909 
7910   Collective
7911 
7912   Input Parameters:
7913 + mat             - the matrix
7914 . shift           - 0 or 1 indicating we want the indices starting at 0 or 1
7915 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7916 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7917                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7918                  always used.
7919 
7920   Output Parameters:
7921 + n    - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7922 . 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
7923 . ja   - the column indices, use `NULL` if not needed
7924 - done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7925            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7926 
7927   Level: developer
7928 
7929   Notes:
7930   You CANNOT change any of the ia[] or ja[] values.
7931 
7932   Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7933 
7934   Fortran Notes:
7935   Use
7936 .vb
7937     PetscInt, pointer :: ia(:),ja(:)
7938     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7939     ! Access the ith and jth entries via ia(i) and ja(j)
7940 .ve
7941   `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7942 
7943 .seealso: [](ch_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7944 @*/
7945 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7946 {
7947   PetscFunctionBegin;
7948   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7949   PetscValidType(mat, 1);
7950   if (n) PetscValidIntPointer(n, 5);
7951   if (ia) PetscValidPointer(ia, 6);
7952   if (ja) PetscValidPointer(ja, 7);
7953   if (done) PetscValidBoolPointer(done, 8);
7954   MatCheckPreallocated(mat, 1);
7955   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7956   else {
7957     if (done) *done = PETSC_TRUE;
7958     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7959     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7960     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7961   }
7962   PetscFunctionReturn(PETSC_SUCCESS);
7963 }
7964 
7965 /*@C
7966   MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7967 
7968   Collective
7969 
7970   Input Parameters:
7971 + mat             - the matrix
7972 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
7973 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7974                 symmetrized
7975 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7976                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7977                  always used.
7978 . n               - number of columns in the (possibly compressed) matrix
7979 . ia              - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7980 - ja              - the row indices
7981 
7982   Output Parameter:
7983 . done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7984 
7985   Level: developer
7986 
7987 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7988 @*/
7989 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7990 {
7991   PetscFunctionBegin;
7992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7993   PetscValidType(mat, 1);
7994   PetscValidIntPointer(n, 5);
7995   if (ia) PetscValidPointer(ia, 6);
7996   if (ja) PetscValidPointer(ja, 7);
7997   PetscValidBoolPointer(done, 8);
7998   MatCheckPreallocated(mat, 1);
7999   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
8000   else {
8001     *done = PETSC_TRUE;
8002     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8003   }
8004   PetscFunctionReturn(PETSC_SUCCESS);
8005 }
8006 
8007 /*@C
8008   MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
8009 
8010   Collective
8011 
8012   Input Parameters:
8013 + mat             - the matrix
8014 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8015 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8016 . inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8017                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8018                  always used.
8019 . n               - size of (possibly compressed) matrix
8020 . ia              - the row pointers
8021 - ja              - the column indices
8022 
8023   Output Parameter:
8024 . done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8025 
8026   Level: developer
8027 
8028   Note:
8029   This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8030   us of the array after it has been restored. If you pass `NULL`, it will
8031   not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8032 
8033   Fortran Notes:
8034   `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8035 
8036 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8037 @*/
8038 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8039 {
8040   PetscFunctionBegin;
8041   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8042   PetscValidType(mat, 1);
8043   if (ia) PetscValidPointer(ia, 6);
8044   if (ja) PetscValidPointer(ja, 7);
8045   if (done) PetscValidBoolPointer(done, 8);
8046   MatCheckPreallocated(mat, 1);
8047 
8048   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8049   else {
8050     if (done) *done = PETSC_TRUE;
8051     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8052     if (n) *n = 0;
8053     if (ia) *ia = NULL;
8054     if (ja) *ja = NULL;
8055   }
8056   PetscFunctionReturn(PETSC_SUCCESS);
8057 }
8058 
8059 /*@C
8060   MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8061 
8062   Collective
8063 
8064   Input Parameters:
8065 + mat             - the matrix
8066 . shift           - 1 or zero indicating we want the indices starting at 0 or 1
8067 . symmetric       - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8068 - inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8069                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8070                  always used.
8071 
8072   Output Parameters:
8073 + n    - size of (possibly compressed) matrix
8074 . ia   - the column pointers
8075 . ja   - the row indices
8076 - done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8077 
8078   Level: developer
8079 
8080 .seealso: [](ch_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8081 @*/
8082 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8083 {
8084   PetscFunctionBegin;
8085   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8086   PetscValidType(mat, 1);
8087   if (ia) PetscValidPointer(ia, 6);
8088   if (ja) PetscValidPointer(ja, 7);
8089   PetscValidBoolPointer(done, 8);
8090   MatCheckPreallocated(mat, 1);
8091 
8092   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8093   else {
8094     *done = PETSC_TRUE;
8095     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8096     if (n) *n = 0;
8097     if (ia) *ia = NULL;
8098     if (ja) *ja = NULL;
8099   }
8100   PetscFunctionReturn(PETSC_SUCCESS);
8101 }
8102 
8103 /*@C
8104   MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8105 
8106   Collective
8107 
8108   Input Parameters:
8109 + mat        - the matrix
8110 . ncolors    - maximum color value
8111 . n          - number of entries in colorarray
8112 - colorarray - array indicating color for each column
8113 
8114   Output Parameter:
8115 . iscoloring - coloring generated using colorarray information
8116 
8117   Level: developer
8118 
8119 .seealso: [](ch_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8120 @*/
8121 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8122 {
8123   PetscFunctionBegin;
8124   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8125   PetscValidType(mat, 1);
8126   PetscValidIntPointer(colorarray, 4);
8127   PetscValidPointer(iscoloring, 5);
8128   MatCheckPreallocated(mat, 1);
8129 
8130   if (!mat->ops->coloringpatch) {
8131     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8132   } else {
8133     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8134   }
8135   PetscFunctionReturn(PETSC_SUCCESS);
8136 }
8137 
8138 /*@
8139   MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8140 
8141   Logically Collective
8142 
8143   Input Parameter:
8144 . mat - the factored matrix to be reset
8145 
8146   Level: developer
8147 
8148   Notes:
8149   This routine should be used only with factored matrices formed by in-place
8150   factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8151   format).  This option can save memory, for example, when solving nonlinear
8152   systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8153   ILU(0) preconditioner.
8154 
8155   One can specify in-place ILU(0) factorization by calling
8156 .vb
8157      PCType(pc,PCILU);
8158      PCFactorSeUseInPlace(pc);
8159 .ve
8160   or by using the options -pc_type ilu -pc_factor_in_place
8161 
8162   In-place factorization ILU(0) can also be used as a local
8163   solver for the blocks within the block Jacobi or additive Schwarz
8164   methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8165   for details on setting local solver options.
8166 
8167   Most users should employ the `KSP` interface for linear solvers
8168   instead of working directly with matrix algebra routines such as this.
8169   See, e.g., `KSPCreate()`.
8170 
8171 .seealso: [](ch_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8172 @*/
8173 PetscErrorCode MatSetUnfactored(Mat mat)
8174 {
8175   PetscFunctionBegin;
8176   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8177   PetscValidType(mat, 1);
8178   MatCheckPreallocated(mat, 1);
8179   mat->factortype = MAT_FACTOR_NONE;
8180   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8181   PetscUseTypeMethod(mat, setunfactored);
8182   PetscFunctionReturn(PETSC_SUCCESS);
8183 }
8184 
8185 /*MC
8186     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8187 
8188     Synopsis:
8189     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8190 
8191     Not Collective
8192 
8193     Input Parameter:
8194 .   x - matrix
8195 
8196     Output Parameters:
8197 +   xx_v - the Fortran pointer to the array
8198 -   ierr - error code
8199 
8200     Example of Usage:
8201 .vb
8202       PetscScalar, pointer xx_v(:,:)
8203       ....
8204       call MatDenseGetArrayF90(x,xx_v,ierr)
8205       a = xx_v(3)
8206       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8207 .ve
8208 
8209     Level: advanced
8210 
8211 .seealso: [](ch_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8212 M*/
8213 
8214 /*MC
8215     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8216     accessed with `MatDenseGetArrayF90()`.
8217 
8218     Synopsis:
8219     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8220 
8221     Not Collective
8222 
8223     Input Parameters:
8224 +   x - matrix
8225 -   xx_v - the Fortran90 pointer to the array
8226 
8227     Output Parameter:
8228 .   ierr - error code
8229 
8230     Example of Usage:
8231 .vb
8232        PetscScalar, pointer xx_v(:,:)
8233        ....
8234        call MatDenseGetArrayF90(x,xx_v,ierr)
8235        a = xx_v(3)
8236        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8237 .ve
8238 
8239     Level: advanced
8240 
8241 .seealso: [](ch_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8242 M*/
8243 
8244 /*MC
8245     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8246 
8247     Synopsis:
8248     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8249 
8250     Not Collective
8251 
8252     Input Parameter:
8253 .   x - matrix
8254 
8255     Output Parameters:
8256 +   xx_v - the Fortran pointer to the array
8257 -   ierr - error code
8258 
8259     Example of Usage:
8260 .vb
8261       PetscScalar, pointer xx_v(:)
8262       ....
8263       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8264       a = xx_v(3)
8265       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8266 .ve
8267 
8268     Level: advanced
8269 
8270 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8271 M*/
8272 
8273 /*MC
8274     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8275     accessed with `MatSeqAIJGetArrayF90()`.
8276 
8277     Synopsis:
8278     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8279 
8280     Not Collective
8281 
8282     Input Parameters:
8283 +   x - matrix
8284 -   xx_v - the Fortran90 pointer to the array
8285 
8286     Output Parameter:
8287 .   ierr - error code
8288 
8289     Example of Usage:
8290 .vb
8291        PetscScalar, pointer xx_v(:)
8292        ....
8293        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8294        a = xx_v(3)
8295        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8296 .ve
8297 
8298     Level: advanced
8299 
8300 .seealso: [](ch_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8301 M*/
8302 
8303 /*@
8304   MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8305   as the original matrix.
8306 
8307   Collective
8308 
8309   Input Parameters:
8310 + mat   - the original matrix
8311 . isrow - parallel `IS` containing the rows this processor should obtain
8312 . 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.
8313 - cll   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8314 
8315   Output Parameter:
8316 . newmat - the new submatrix, of the same type as the original matrix
8317 
8318   Level: advanced
8319 
8320   Notes:
8321   The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8322 
8323   Some matrix types place restrictions on the row and column indices, such
8324   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;
8325   for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8326 
8327   The index sets may not have duplicate entries.
8328 
8329   The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8330   the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8331   to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8332   will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8333   you are finished using it.
8334 
8335   The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8336   the input matrix.
8337 
8338   If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8339 
8340   Example usage:
8341   Consider the following 8x8 matrix with 34 non-zero values, that is
8342   assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8343   proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8344   as follows
8345 .vb
8346             1  2  0  |  0  3  0  |  0  4
8347     Proc0   0  5  6  |  7  0  0  |  8  0
8348             9  0 10  | 11  0  0  | 12  0
8349     -------------------------------------
8350            13  0 14  | 15 16 17  |  0  0
8351     Proc1   0 18  0  | 19 20 21  |  0  0
8352             0  0  0  | 22 23  0  | 24  0
8353     -------------------------------------
8354     Proc2  25 26 27  |  0  0 28  | 29  0
8355            30  0  0  | 31 32 33  |  0 34
8356 .ve
8357 
8358   Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8359 
8360 .vb
8361             2  0  |  0  3  0  |  0
8362     Proc0   5  6  |  7  0  0  |  8
8363     -------------------------------
8364     Proc1  18  0  | 19 20 21  |  0
8365     -------------------------------
8366     Proc2  26 27  |  0  0 28  | 29
8367             0  0  | 31 32 33  |  0
8368 .ve
8369 
8370 .seealso: [](ch_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8371 @*/
8372 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8373 {
8374   PetscMPIInt size;
8375   Mat        *local;
8376   IS          iscoltmp;
8377   PetscBool   flg;
8378 
8379   PetscFunctionBegin;
8380   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8381   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8382   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8383   PetscValidPointer(newmat, 5);
8384   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8385   PetscValidType(mat, 1);
8386   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8387   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8388 
8389   MatCheckPreallocated(mat, 1);
8390   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8391 
8392   if (!iscol || isrow == iscol) {
8393     PetscBool   stride;
8394     PetscMPIInt grabentirematrix = 0, grab;
8395     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8396     if (stride) {
8397       PetscInt first, step, n, rstart, rend;
8398       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8399       if (step == 1) {
8400         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8401         if (rstart == first) {
8402           PetscCall(ISGetLocalSize(isrow, &n));
8403           if (n == rend - rstart) grabentirematrix = 1;
8404         }
8405       }
8406     }
8407     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8408     if (grab) {
8409       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8410       if (cll == MAT_INITIAL_MATRIX) {
8411         *newmat = mat;
8412         PetscCall(PetscObjectReference((PetscObject)mat));
8413       }
8414       PetscFunctionReturn(PETSC_SUCCESS);
8415     }
8416   }
8417 
8418   if (!iscol) {
8419     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8420   } else {
8421     iscoltmp = iscol;
8422   }
8423 
8424   /* if original matrix is on just one processor then use submatrix generated */
8425   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8426     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8427     goto setproperties;
8428   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8429     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8430     *newmat = *local;
8431     PetscCall(PetscFree(local));
8432     goto setproperties;
8433   } else if (!mat->ops->createsubmatrix) {
8434     /* Create a new matrix type that implements the operation using the full matrix */
8435     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8436     switch (cll) {
8437     case MAT_INITIAL_MATRIX:
8438       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8439       break;
8440     case MAT_REUSE_MATRIX:
8441       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8442       break;
8443     default:
8444       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8445     }
8446     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8447     goto setproperties;
8448   }
8449 
8450   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8451   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8452   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8453 
8454 setproperties:
8455   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8456   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8457   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8458   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8459   PetscFunctionReturn(PETSC_SUCCESS);
8460 }
8461 
8462 /*@
8463   MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8464 
8465   Not Collective
8466 
8467   Input Parameters:
8468 + A - the matrix we wish to propagate options from
8469 - B - the matrix we wish to propagate options to
8470 
8471   Level: beginner
8472 
8473   Note:
8474   Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8475 
8476 .seealso: [](ch_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
8477 @*/
8478 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8479 {
8480   PetscFunctionBegin;
8481   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8482   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8483   B->symmetry_eternal            = A->symmetry_eternal;
8484   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8485   B->symmetric                   = A->symmetric;
8486   B->structurally_symmetric      = A->structurally_symmetric;
8487   B->spd                         = A->spd;
8488   B->hermitian                   = A->hermitian;
8489   PetscFunctionReturn(PETSC_SUCCESS);
8490 }
8491 
8492 /*@
8493   MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8494   used during the assembly process to store values that belong to
8495   other processors.
8496 
8497   Not Collective
8498 
8499   Input Parameters:
8500 + mat   - the matrix
8501 . size  - the initial size of the stash.
8502 - bsize - the initial size of the block-stash(if used).
8503 
8504   Options Database Keys:
8505 + -matstash_initial_size <size> or <size0,size1,...sizep-1>            - set initial size
8506 - -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1> - set initial block size
8507 
8508   Level: intermediate
8509 
8510   Notes:
8511   The block-stash is used for values set with `MatSetValuesBlocked()` while
8512   the stash is used for values set with `MatSetValues()`
8513 
8514   Run with the option -info and look for output of the form
8515   MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8516   to determine the appropriate value, MM, to use for size and
8517   MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8518   to determine the value, BMM to use for bsize
8519 
8520 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8521 @*/
8522 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8523 {
8524   PetscFunctionBegin;
8525   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8526   PetscValidType(mat, 1);
8527   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8528   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8529   PetscFunctionReturn(PETSC_SUCCESS);
8530 }
8531 
8532 /*@
8533   MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8534   the matrix
8535 
8536   Neighbor-wise Collective
8537 
8538   Input Parameters:
8539 + A - the matrix
8540 . x - the vector to be multiplied by the interpolation operator
8541 - y - the vector to be added to the result
8542 
8543   Output Parameter:
8544 . w - the resulting vector
8545 
8546   Level: intermediate
8547 
8548   Notes:
8549   `w` may be the same vector as `y`.
8550 
8551   This allows one to use either the restriction or interpolation (its transpose)
8552   matrix to do the interpolation
8553 
8554 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8555 @*/
8556 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8557 {
8558   PetscInt M, N, Ny;
8559 
8560   PetscFunctionBegin;
8561   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8562   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8563   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8564   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8565   PetscCall(MatGetSize(A, &M, &N));
8566   PetscCall(VecGetSize(y, &Ny));
8567   if (M == Ny) {
8568     PetscCall(MatMultAdd(A, x, y, w));
8569   } else {
8570     PetscCall(MatMultTransposeAdd(A, x, y, w));
8571   }
8572   PetscFunctionReturn(PETSC_SUCCESS);
8573 }
8574 
8575 /*@
8576   MatInterpolate - y = A*x or A'*x depending on the shape of
8577   the matrix
8578 
8579   Neighbor-wise Collective
8580 
8581   Input Parameters:
8582 + A - the matrix
8583 - x - the vector to be interpolated
8584 
8585   Output Parameter:
8586 . y - the resulting vector
8587 
8588   Level: intermediate
8589 
8590   Note:
8591   This allows one to use either the restriction or interpolation (its transpose)
8592   matrix to do the interpolation
8593 
8594 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8595 @*/
8596 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8597 {
8598   PetscInt M, N, Ny;
8599 
8600   PetscFunctionBegin;
8601   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8602   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8603   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8604   PetscCall(MatGetSize(A, &M, &N));
8605   PetscCall(VecGetSize(y, &Ny));
8606   if (M == Ny) {
8607     PetscCall(MatMult(A, x, y));
8608   } else {
8609     PetscCall(MatMultTranspose(A, x, y));
8610   }
8611   PetscFunctionReturn(PETSC_SUCCESS);
8612 }
8613 
8614 /*@
8615   MatRestrict - y = A*x or A'*x
8616 
8617   Neighbor-wise Collective
8618 
8619   Input Parameters:
8620 + A - the matrix
8621 - x - the vector to be restricted
8622 
8623   Output Parameter:
8624 . y - the resulting vector
8625 
8626   Level: intermediate
8627 
8628   Note:
8629   This allows one to use either the restriction or interpolation (its transpose)
8630   matrix to do the restriction
8631 
8632 .seealso: [](ch_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8633 @*/
8634 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8635 {
8636   PetscInt M, N, Ny;
8637 
8638   PetscFunctionBegin;
8639   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8640   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8641   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8642   PetscCall(MatGetSize(A, &M, &N));
8643   PetscCall(VecGetSize(y, &Ny));
8644   if (M == Ny) {
8645     PetscCall(MatMult(A, x, y));
8646   } else {
8647     PetscCall(MatMultTranspose(A, x, y));
8648   }
8649   PetscFunctionReturn(PETSC_SUCCESS);
8650 }
8651 
8652 /*@
8653   MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8654 
8655   Neighbor-wise Collective
8656 
8657   Input Parameters:
8658 + A - the matrix
8659 . x - the input dense matrix to be multiplied
8660 - w - the input dense matrix to be added to the result
8661 
8662   Output Parameter:
8663 . y - the output dense matrix
8664 
8665   Level: intermediate
8666 
8667   Note:
8668   This allows one to use either the restriction or interpolation (its transpose)
8669   matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8670   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8671 
8672 .seealso: [](ch_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8673 @*/
8674 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8675 {
8676   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8677   PetscBool trans = PETSC_TRUE;
8678   MatReuse  reuse = MAT_INITIAL_MATRIX;
8679 
8680   PetscFunctionBegin;
8681   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8682   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8683   PetscValidType(x, 2);
8684   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8685   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8686   PetscCall(MatGetSize(A, &M, &N));
8687   PetscCall(MatGetSize(x, &Mx, &Nx));
8688   if (N == Mx) trans = PETSC_FALSE;
8689   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);
8690   Mo = trans ? N : M;
8691   if (*y) {
8692     PetscCall(MatGetSize(*y, &My, &Ny));
8693     if (Mo == My && Nx == Ny) {
8694       reuse = MAT_REUSE_MATRIX;
8695     } else {
8696       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);
8697       PetscCall(MatDestroy(y));
8698     }
8699   }
8700 
8701   if (w && *y == w) { /* this is to minimize changes in PCMG */
8702     PetscBool flg;
8703 
8704     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8705     if (w) {
8706       PetscInt My, Ny, Mw, Nw;
8707 
8708       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8709       PetscCall(MatGetSize(*y, &My, &Ny));
8710       PetscCall(MatGetSize(w, &Mw, &Nw));
8711       if (!flg || My != Mw || Ny != Nw) w = NULL;
8712     }
8713     if (!w) {
8714       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8715       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8716       PetscCall(PetscObjectDereference((PetscObject)w));
8717     } else {
8718       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8719     }
8720   }
8721   if (!trans) {
8722     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8723   } else {
8724     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8725   }
8726   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8727   PetscFunctionReturn(PETSC_SUCCESS);
8728 }
8729 
8730 /*@
8731   MatMatInterpolate - Y = A*X or A'*X
8732 
8733   Neighbor-wise Collective
8734 
8735   Input Parameters:
8736 + A - the matrix
8737 - x - the input dense matrix
8738 
8739   Output Parameter:
8740 . y - the output dense matrix
8741 
8742   Level: intermediate
8743 
8744   Note:
8745   This allows one to use either the restriction or interpolation (its transpose)
8746   matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8747   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8748 
8749 .seealso: [](ch_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8750 @*/
8751 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8752 {
8753   PetscFunctionBegin;
8754   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8755   PetscFunctionReturn(PETSC_SUCCESS);
8756 }
8757 
8758 /*@
8759   MatMatRestrict - Y = A*X or A'*X
8760 
8761   Neighbor-wise Collective
8762 
8763   Input Parameters:
8764 + A - the matrix
8765 - x - the input dense matrix
8766 
8767   Output Parameter:
8768 . y - the output dense matrix
8769 
8770   Level: intermediate
8771 
8772   Note:
8773   This allows one to use either the restriction or interpolation (its transpose)
8774   matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8775   otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8776 
8777 .seealso: [](ch_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8778 @*/
8779 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8780 {
8781   PetscFunctionBegin;
8782   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8783   PetscFunctionReturn(PETSC_SUCCESS);
8784 }
8785 
8786 /*@
8787   MatGetNullSpace - retrieves the null space of a matrix.
8788 
8789   Logically Collective
8790 
8791   Input Parameters:
8792 + mat    - the matrix
8793 - nullsp - the null space object
8794 
8795   Level: developer
8796 
8797 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8798 @*/
8799 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8800 {
8801   PetscFunctionBegin;
8802   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8803   PetscValidPointer(nullsp, 2);
8804   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8805   PetscFunctionReturn(PETSC_SUCCESS);
8806 }
8807 
8808 /*@
8809   MatSetNullSpace - attaches a null space to a matrix.
8810 
8811   Logically Collective
8812 
8813   Input Parameters:
8814 + mat    - the matrix
8815 - nullsp - the null space object
8816 
8817   Level: advanced
8818 
8819   Notes:
8820   This null space is used by the `KSP` linear solvers to solve singular systems.
8821 
8822   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`
8823 
8824   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
8825   to zero but the linear system will still be solved in a least squares sense.
8826 
8827   The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8828   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).
8829   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
8830   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
8831   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).
8832   This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8833 
8834   If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8835   `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8836   routine also automatically calls `MatSetTransposeNullSpace()`.
8837 
8838   The user should call `MatNullSpaceDestroy()`.
8839 
8840 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8841           `KSPSetPCSide()`
8842 @*/
8843 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8844 {
8845   PetscFunctionBegin;
8846   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8847   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8848   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8849   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8850   mat->nullsp = nullsp;
8851   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8852   PetscFunctionReturn(PETSC_SUCCESS);
8853 }
8854 
8855 /*@
8856   MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8857 
8858   Logically Collective
8859 
8860   Input Parameters:
8861 + mat    - the matrix
8862 - nullsp - the null space object
8863 
8864   Level: developer
8865 
8866 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8867 @*/
8868 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8869 {
8870   PetscFunctionBegin;
8871   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8872   PetscValidType(mat, 1);
8873   PetscValidPointer(nullsp, 2);
8874   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8875   PetscFunctionReturn(PETSC_SUCCESS);
8876 }
8877 
8878 /*@
8879   MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8880 
8881   Logically Collective
8882 
8883   Input Parameters:
8884 + mat    - the matrix
8885 - nullsp - the null space object
8886 
8887   Level: advanced
8888 
8889   Notes:
8890   This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8891 
8892   See `MatSetNullSpace()`
8893 
8894 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8895 @*/
8896 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8897 {
8898   PetscFunctionBegin;
8899   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8900   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8901   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8902   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8903   mat->transnullsp = nullsp;
8904   PetscFunctionReturn(PETSC_SUCCESS);
8905 }
8906 
8907 /*@
8908   MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8909   This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8910 
8911   Logically Collective
8912 
8913   Input Parameters:
8914 + mat    - the matrix
8915 - nullsp - the null space object
8916 
8917   Level: advanced
8918 
8919   Notes:
8920   Overwrites any previous near null space that may have been attached
8921 
8922   You can remove the null space by calling this routine with an nullsp of `NULL`
8923 
8924 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8925 @*/
8926 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8927 {
8928   PetscFunctionBegin;
8929   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8930   PetscValidType(mat, 1);
8931   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8932   MatCheckPreallocated(mat, 1);
8933   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8934   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8935   mat->nearnullsp = nullsp;
8936   PetscFunctionReturn(PETSC_SUCCESS);
8937 }
8938 
8939 /*@
8940   MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8941 
8942   Not Collective
8943 
8944   Input Parameter:
8945 . mat - the matrix
8946 
8947   Output Parameter:
8948 . nullsp - the null space object, `NULL` if not set
8949 
8950   Level: advanced
8951 
8952 .seealso: [](ch_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8953 @*/
8954 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8955 {
8956   PetscFunctionBegin;
8957   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8958   PetscValidType(mat, 1);
8959   PetscValidPointer(nullsp, 2);
8960   MatCheckPreallocated(mat, 1);
8961   *nullsp = mat->nearnullsp;
8962   PetscFunctionReturn(PETSC_SUCCESS);
8963 }
8964 
8965 /*@C
8966   MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8967 
8968   Collective
8969 
8970   Input Parameters:
8971 + mat  - the matrix
8972 . row  - row/column permutation
8973 - info - information on desired factorization process
8974 
8975   Level: developer
8976 
8977   Notes:
8978   Probably really in-place only when level of fill is zero, otherwise allocates
8979   new space to store factored matrix and deletes previous memory.
8980 
8981   Most users should employ the `KSP` interface for linear solvers
8982   instead of working directly with matrix algebra routines such as this.
8983   See, e.g., `KSPCreate()`.
8984 
8985   Developer Notes:
8986   The Fortran interface is not autogenerated as the
8987   interface definition cannot be generated correctly [due to `MatFactorInfo`]
8988 
8989 .seealso: [](ch_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8990 @*/
8991 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8992 {
8993   PetscFunctionBegin;
8994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8995   PetscValidType(mat, 1);
8996   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8997   PetscValidPointer(info, 3);
8998   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8999   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9000   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9001   MatCheckPreallocated(mat, 1);
9002   PetscUseTypeMethod(mat, iccfactor, row, info);
9003   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9004   PetscFunctionReturn(PETSC_SUCCESS);
9005 }
9006 
9007 /*@
9008   MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
9009   ghosted ones.
9010 
9011   Not Collective
9012 
9013   Input Parameters:
9014 + mat  - the matrix
9015 - diag - the diagonal values, including ghost ones
9016 
9017   Level: developer
9018 
9019   Notes:
9020   Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
9021 
9022   This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
9023 
9024 .seealso: [](ch_matrices), `Mat`, `MatDiagonalScale()`
9025 @*/
9026 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
9027 {
9028   PetscMPIInt size;
9029 
9030   PetscFunctionBegin;
9031   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9032   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9033   PetscValidType(mat, 1);
9034 
9035   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9036   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9037   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9038   if (size == 1) {
9039     PetscInt n, m;
9040     PetscCall(VecGetSize(diag, &n));
9041     PetscCall(MatGetSize(mat, NULL, &m));
9042     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9043     PetscCall(MatDiagonalScale(mat, NULL, diag));
9044   } else {
9045     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9046   }
9047   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9048   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9049   PetscFunctionReturn(PETSC_SUCCESS);
9050 }
9051 
9052 /*@
9053   MatGetInertia - Gets the inertia from a factored matrix
9054 
9055   Collective
9056 
9057   Input Parameter:
9058 . mat - the matrix
9059 
9060   Output Parameters:
9061 + nneg  - number of negative eigenvalues
9062 . nzero - number of zero eigenvalues
9063 - npos  - number of positive eigenvalues
9064 
9065   Level: advanced
9066 
9067   Note:
9068   Matrix must have been factored by `MatCholeskyFactor()`
9069 
9070 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9071 @*/
9072 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9073 {
9074   PetscFunctionBegin;
9075   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9076   PetscValidType(mat, 1);
9077   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9078   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9079   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9080   PetscFunctionReturn(PETSC_SUCCESS);
9081 }
9082 
9083 /*@C
9084   MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9085 
9086   Neighbor-wise Collective
9087 
9088   Input Parameters:
9089 + mat - the factored matrix obtained with `MatGetFactor()`
9090 - b   - the right-hand-side vectors
9091 
9092   Output Parameter:
9093 . x - the result vectors
9094 
9095   Level: developer
9096 
9097   Note:
9098   The vectors `b` and `x` cannot be the same.  I.e., one cannot
9099   call `MatSolves`(A,x,x).
9100 
9101 .seealso: [](ch_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9102 @*/
9103 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9104 {
9105   PetscFunctionBegin;
9106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9107   PetscValidType(mat, 1);
9108   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9109   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9110   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9111 
9112   MatCheckPreallocated(mat, 1);
9113   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9114   PetscUseTypeMethod(mat, solves, b, x);
9115   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9116   PetscFunctionReturn(PETSC_SUCCESS);
9117 }
9118 
9119 /*@
9120   MatIsSymmetric - Test whether a matrix is symmetric
9121 
9122   Collective
9123 
9124   Input Parameters:
9125 + A   - the matrix to test
9126 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9127 
9128   Output Parameter:
9129 . flg - the result
9130 
9131   Level: intermediate
9132 
9133   Notes:
9134   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9135 
9136   If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9137 
9138   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9139   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9140 
9141 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9142           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`
9143 @*/
9144 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9145 {
9146   PetscFunctionBegin;
9147   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9148   PetscValidBoolPointer(flg, 3);
9149 
9150   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9151   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9152   else {
9153     PetscUseTypeMethod(A, issymmetric, tol, flg);
9154     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9155   }
9156   PetscFunctionReturn(PETSC_SUCCESS);
9157 }
9158 
9159 /*@
9160   MatIsHermitian - Test whether a matrix is Hermitian
9161 
9162   Collective
9163 
9164   Input Parameters:
9165 + A   - the matrix to test
9166 - tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9167 
9168   Output Parameter:
9169 . flg - the result
9170 
9171   Level: intermediate
9172 
9173   Notes:
9174   For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9175 
9176   If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9177 
9178   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9179   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9180 
9181 .seealso: [](ch_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9182           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`
9183 @*/
9184 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9185 {
9186   PetscFunctionBegin;
9187   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9188   PetscValidBoolPointer(flg, 3);
9189 
9190   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9191   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9192   else {
9193     PetscUseTypeMethod(A, ishermitian, tol, flg);
9194     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9195   }
9196   PetscFunctionReturn(PETSC_SUCCESS);
9197 }
9198 
9199 /*@
9200   MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9201 
9202   Not Collective
9203 
9204   Input Parameter:
9205 . A - the matrix to check
9206 
9207   Output Parameters:
9208 + set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9209 - flg - the result (only valid if set is `PETSC_TRUE`)
9210 
9211   Level: advanced
9212 
9213   Notes:
9214   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9215   if you want it explicitly checked
9216 
9217   One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9218   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9219 
9220 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9221 @*/
9222 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9223 {
9224   PetscFunctionBegin;
9225   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9226   PetscValidBoolPointer(set, 2);
9227   PetscValidBoolPointer(flg, 3);
9228   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9229     *set = PETSC_TRUE;
9230     *flg = PetscBool3ToBool(A->symmetric);
9231   } else {
9232     *set = PETSC_FALSE;
9233   }
9234   PetscFunctionReturn(PETSC_SUCCESS);
9235 }
9236 
9237 /*@
9238   MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9239 
9240   Not Collective
9241 
9242   Input Parameter:
9243 . A - the matrix to check
9244 
9245   Output Parameters:
9246 + set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9247 - flg - the result (only valid if set is `PETSC_TRUE`)
9248 
9249   Level: advanced
9250 
9251   Notes:
9252   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9253 
9254   One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9255   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9256 
9257 .seealso: [](ch_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9258 @*/
9259 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9260 {
9261   PetscFunctionBegin;
9262   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9263   PetscValidBoolPointer(set, 2);
9264   PetscValidBoolPointer(flg, 3);
9265   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9266     *set = PETSC_TRUE;
9267     *flg = PetscBool3ToBool(A->spd);
9268   } else {
9269     *set = PETSC_FALSE;
9270   }
9271   PetscFunctionReturn(PETSC_SUCCESS);
9272 }
9273 
9274 /*@
9275   MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9276 
9277   Not Collective
9278 
9279   Input Parameter:
9280 . A - the matrix to check
9281 
9282   Output Parameters:
9283 + set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9284 - flg - the result (only valid if set is `PETSC_TRUE`)
9285 
9286   Level: advanced
9287 
9288   Notes:
9289   Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9290   if you want it explicitly checked
9291 
9292   One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9293   after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9294 
9295 .seealso: [](ch_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9296 @*/
9297 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9298 {
9299   PetscFunctionBegin;
9300   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9301   PetscValidBoolPointer(set, 2);
9302   PetscValidBoolPointer(flg, 3);
9303   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9304     *set = PETSC_TRUE;
9305     *flg = PetscBool3ToBool(A->hermitian);
9306   } else {
9307     *set = PETSC_FALSE;
9308   }
9309   PetscFunctionReturn(PETSC_SUCCESS);
9310 }
9311 
9312 /*@
9313   MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9314 
9315   Collective
9316 
9317   Input Parameter:
9318 . A - the matrix to test
9319 
9320   Output Parameter:
9321 . flg - the result
9322 
9323   Level: intermediate
9324 
9325   Notes:
9326   If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9327 
9328   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
9329   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9330 
9331 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9332 @*/
9333 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9334 {
9335   PetscFunctionBegin;
9336   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9337   PetscValidBoolPointer(flg, 2);
9338   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9339     *flg = PetscBool3ToBool(A->structurally_symmetric);
9340   } else {
9341     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9342     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9343   }
9344   PetscFunctionReturn(PETSC_SUCCESS);
9345 }
9346 
9347 /*@
9348   MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9349 
9350   Not Collective
9351 
9352   Input Parameter:
9353 . A - the matrix to check
9354 
9355   Output Parameters:
9356 + set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9357 - flg - the result (only valid if set is PETSC_TRUE)
9358 
9359   Level: advanced
9360 
9361   Notes:
9362   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
9363   symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9364 
9365   Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9366 
9367 .seealso: [](ch_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9368 @*/
9369 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9370 {
9371   PetscFunctionBegin;
9372   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9373   PetscValidBoolPointer(set, 2);
9374   PetscValidBoolPointer(flg, 3);
9375   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9376     *set = PETSC_TRUE;
9377     *flg = PetscBool3ToBool(A->structurally_symmetric);
9378   } else {
9379     *set = PETSC_FALSE;
9380   }
9381   PetscFunctionReturn(PETSC_SUCCESS);
9382 }
9383 
9384 /*@
9385   MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9386   to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9387 
9388   Not Collective
9389 
9390   Input Parameter:
9391 . mat - the matrix
9392 
9393   Output Parameters:
9394 + nstash    - the size of the stash
9395 . reallocs  - the number of additional mallocs incurred.
9396 . bnstash   - the size of the block stash
9397 - breallocs - the number of additional mallocs incurred.in the block stash
9398 
9399   Level: advanced
9400 
9401 .seealso: [](ch_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9402 @*/
9403 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9404 {
9405   PetscFunctionBegin;
9406   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9407   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9408   PetscFunctionReturn(PETSC_SUCCESS);
9409 }
9410 
9411 /*@C
9412   MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9413   parallel layout, `PetscLayout` for rows and columns
9414 
9415   Collective
9416 
9417   Input Parameter:
9418 . mat - the matrix
9419 
9420   Output Parameters:
9421 + right - (optional) vector that the matrix can be multiplied against
9422 - left  - (optional) vector that the matrix vector product can be stored in
9423 
9424   Level: advanced
9425 
9426   Notes:
9427   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()`.
9428 
9429   These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9430 
9431 .seealso: [](ch_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9432 @*/
9433 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9434 {
9435   PetscFunctionBegin;
9436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9437   PetscValidType(mat, 1);
9438   if (mat->ops->getvecs) {
9439     PetscUseTypeMethod(mat, getvecs, right, left);
9440   } else {
9441     if (right) {
9442       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9443       PetscCall(VecCreateWithLayout_Private(mat->cmap, right));
9444       PetscCall(VecSetType(*right, mat->defaultvectype));
9445 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9446       if (mat->boundtocpu && mat->bindingpropagates) {
9447         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9448         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9449       }
9450 #endif
9451     }
9452     if (left) {
9453       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9454       PetscCall(VecCreateWithLayout_Private(mat->rmap, left));
9455       PetscCall(VecSetType(*left, mat->defaultvectype));
9456 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9457       if (mat->boundtocpu && mat->bindingpropagates) {
9458         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9459         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9460       }
9461 #endif
9462     }
9463   }
9464   PetscFunctionReturn(PETSC_SUCCESS);
9465 }
9466 
9467 /*@C
9468   MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9469   with default values.
9470 
9471   Not Collective
9472 
9473   Input Parameter:
9474 . info - the `MatFactorInfo` data structure
9475 
9476   Level: developer
9477 
9478   Notes:
9479   The solvers are generally used through the `KSP` and `PC` objects, for example
9480   `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9481 
9482   Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9483 
9484   Developer Notes:
9485   The Fortran interface is not autogenerated as the
9486   interface definition cannot be generated correctly [due to `MatFactorInfo`]
9487 
9488 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9489 @*/
9490 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9491 {
9492   PetscFunctionBegin;
9493   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9494   PetscFunctionReturn(PETSC_SUCCESS);
9495 }
9496 
9497 /*@
9498   MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9499 
9500   Collective
9501 
9502   Input Parameters:
9503 + mat - the factored matrix
9504 - is  - the index set defining the Schur indices (0-based)
9505 
9506   Level: advanced
9507 
9508   Notes:
9509   Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9510 
9511   You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9512 
9513   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9514 
9515 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9516           `MatFactorSolveSchurComplementTranspose()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9517 @*/
9518 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9519 {
9520   PetscErrorCode (*f)(Mat, IS);
9521 
9522   PetscFunctionBegin;
9523   PetscValidType(mat, 1);
9524   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9525   PetscValidType(is, 2);
9526   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9527   PetscCheckSameComm(mat, 1, is, 2);
9528   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9529   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9530   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9531   PetscCall(MatDestroy(&mat->schur));
9532   PetscCall((*f)(mat, is));
9533   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9534   PetscFunctionReturn(PETSC_SUCCESS);
9535 }
9536 
9537 /*@
9538   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9539 
9540   Logically Collective
9541 
9542   Input Parameters:
9543 + F      - the factored matrix obtained by calling `MatGetFactor()`
9544 . S      - location where to return the Schur complement, can be `NULL`
9545 - status - the status of the Schur complement matrix, can be `NULL`
9546 
9547   Level: advanced
9548 
9549   Notes:
9550   You must call `MatFactorSetSchurIS()` before calling this routine.
9551 
9552   This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9553 
9554   The routine provides a copy of the Schur matrix stored within the solver data structures.
9555   The caller must destroy the object when it is no longer needed.
9556   If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9557 
9558   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)
9559 
9560   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9561 
9562   Developer Notes:
9563   The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9564   matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9565 
9566 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9567 @*/
9568 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9569 {
9570   PetscFunctionBegin;
9571   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9572   if (S) PetscValidPointer(S, 2);
9573   if (status) PetscValidPointer(status, 3);
9574   if (S) {
9575     PetscErrorCode (*f)(Mat, Mat *);
9576 
9577     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9578     if (f) {
9579       PetscCall((*f)(F, S));
9580     } else {
9581       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9582     }
9583   }
9584   if (status) *status = F->schur_status;
9585   PetscFunctionReturn(PETSC_SUCCESS);
9586 }
9587 
9588 /*@
9589   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9590 
9591   Logically Collective
9592 
9593   Input Parameters:
9594 + F      - the factored matrix obtained by calling `MatGetFactor()`
9595 . S      - location where to return the Schur complement, can be `NULL`
9596 - status - the status of the Schur complement matrix, can be `NULL`
9597 
9598   Level: advanced
9599 
9600   Notes:
9601   You must call `MatFactorSetSchurIS()` before calling this routine.
9602 
9603   Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9604 
9605   The routine returns a the Schur Complement stored within the data structures of the solver.
9606 
9607   If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9608 
9609   The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9610 
9611   Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9612 
9613   See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9614 
9615 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9616 @*/
9617 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9618 {
9619   PetscFunctionBegin;
9620   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9621   if (S) PetscValidPointer(S, 2);
9622   if (status) PetscValidPointer(status, 3);
9623   if (S) *S = F->schur;
9624   if (status) *status = F->schur_status;
9625   PetscFunctionReturn(PETSC_SUCCESS);
9626 }
9627 
9628 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9629 {
9630   Mat S = F->schur;
9631 
9632   PetscFunctionBegin;
9633   switch (F->schur_status) {
9634   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9635   case MAT_FACTOR_SCHUR_INVERTED:
9636     if (S) {
9637       S->ops->solve             = NULL;
9638       S->ops->matsolve          = NULL;
9639       S->ops->solvetranspose    = NULL;
9640       S->ops->matsolvetranspose = NULL;
9641       S->ops->solveadd          = NULL;
9642       S->ops->solvetransposeadd = NULL;
9643       S->factortype             = MAT_FACTOR_NONE;
9644       PetscCall(PetscFree(S->solvertype));
9645     }
9646   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9647     break;
9648   default:
9649     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9650   }
9651   PetscFunctionReturn(PETSC_SUCCESS);
9652 }
9653 
9654 /*@
9655   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9656 
9657   Logically Collective
9658 
9659   Input Parameters:
9660 + F      - the factored matrix obtained by calling `MatGetFactor()`
9661 . S      - location where the Schur complement is stored
9662 - status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9663 
9664   Level: advanced
9665 
9666 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9667 @*/
9668 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9669 {
9670   PetscFunctionBegin;
9671   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9672   if (S) {
9673     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9674     *S = NULL;
9675   }
9676   F->schur_status = status;
9677   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9678   PetscFunctionReturn(PETSC_SUCCESS);
9679 }
9680 
9681 /*@
9682   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9683 
9684   Logically Collective
9685 
9686   Input Parameters:
9687 + F   - the factored matrix obtained by calling `MatGetFactor()`
9688 . rhs - location where the right hand side of the Schur complement system is stored
9689 - sol - location where the solution of the Schur complement system has to be returned
9690 
9691   Level: advanced
9692 
9693   Notes:
9694   The sizes of the vectors should match the size of the Schur complement
9695 
9696   Must be called after `MatFactorSetSchurIS()`
9697 
9698 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9699 @*/
9700 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9701 {
9702   PetscFunctionBegin;
9703   PetscValidType(F, 1);
9704   PetscValidType(rhs, 2);
9705   PetscValidType(sol, 3);
9706   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9707   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9708   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9709   PetscCheckSameComm(F, 1, rhs, 2);
9710   PetscCheckSameComm(F, 1, sol, 3);
9711   PetscCall(MatFactorFactorizeSchurComplement(F));
9712   switch (F->schur_status) {
9713   case MAT_FACTOR_SCHUR_FACTORED:
9714     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9715     break;
9716   case MAT_FACTOR_SCHUR_INVERTED:
9717     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9718     break;
9719   default:
9720     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9721   }
9722   PetscFunctionReturn(PETSC_SUCCESS);
9723 }
9724 
9725 /*@
9726   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9727 
9728   Logically Collective
9729 
9730   Input Parameters:
9731 + F   - the factored matrix obtained by calling `MatGetFactor()`
9732 . rhs - location where the right hand side of the Schur complement system is stored
9733 - sol - location where the solution of the Schur complement system has to be returned
9734 
9735   Level: advanced
9736 
9737   Notes:
9738   The sizes of the vectors should match the size of the Schur complement
9739 
9740   Must be called after `MatFactorSetSchurIS()`
9741 
9742 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9743 @*/
9744 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9745 {
9746   PetscFunctionBegin;
9747   PetscValidType(F, 1);
9748   PetscValidType(rhs, 2);
9749   PetscValidType(sol, 3);
9750   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9751   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9752   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9753   PetscCheckSameComm(F, 1, rhs, 2);
9754   PetscCheckSameComm(F, 1, sol, 3);
9755   PetscCall(MatFactorFactorizeSchurComplement(F));
9756   switch (F->schur_status) {
9757   case MAT_FACTOR_SCHUR_FACTORED:
9758     PetscCall(MatSolve(F->schur, rhs, sol));
9759     break;
9760   case MAT_FACTOR_SCHUR_INVERTED:
9761     PetscCall(MatMult(F->schur, rhs, sol));
9762     break;
9763   default:
9764     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9765   }
9766   PetscFunctionReturn(PETSC_SUCCESS);
9767 }
9768 
9769 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9770 #if PetscDefined(HAVE_CUDA)
9771 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9772 #endif
9773 
9774 /* Schur status updated in the interface */
9775 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9776 {
9777   Mat S = F->schur;
9778 
9779   PetscFunctionBegin;
9780   if (S) {
9781     PetscMPIInt size;
9782     PetscBool   isdense, isdensecuda;
9783 
9784     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9785     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9786     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9787     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9788     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9789     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9790     if (isdense) {
9791       PetscCall(MatSeqDenseInvertFactors_Private(S));
9792     } else if (isdensecuda) {
9793 #if defined(PETSC_HAVE_CUDA)
9794       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9795 #endif
9796     }
9797     // HIP??????????????
9798     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9799   }
9800   PetscFunctionReturn(PETSC_SUCCESS);
9801 }
9802 
9803 /*@
9804   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9805 
9806   Logically Collective
9807 
9808   Input Parameter:
9809 . F - the factored matrix obtained by calling `MatGetFactor()`
9810 
9811   Level: advanced
9812 
9813   Notes:
9814   Must be called after `MatFactorSetSchurIS()`.
9815 
9816   Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9817 
9818 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9819 @*/
9820 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9821 {
9822   PetscFunctionBegin;
9823   PetscValidType(F, 1);
9824   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9825   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9826   PetscCall(MatFactorFactorizeSchurComplement(F));
9827   PetscCall(MatFactorInvertSchurComplement_Private(F));
9828   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9829   PetscFunctionReturn(PETSC_SUCCESS);
9830 }
9831 
9832 /*@
9833   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9834 
9835   Logically Collective
9836 
9837   Input Parameter:
9838 . F - the factored matrix obtained by calling `MatGetFactor()`
9839 
9840   Level: advanced
9841 
9842   Note:
9843   Must be called after `MatFactorSetSchurIS()`
9844 
9845 .seealso: [](ch_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9846 @*/
9847 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9848 {
9849   MatFactorInfo info;
9850 
9851   PetscFunctionBegin;
9852   PetscValidType(F, 1);
9853   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9854   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9855   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9856   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9857   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9858     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9859   } else {
9860     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9861   }
9862   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9863   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9864   PetscFunctionReturn(PETSC_SUCCESS);
9865 }
9866 
9867 /*@
9868   MatPtAP - Creates the matrix product C = P^T * A * P
9869 
9870   Neighbor-wise Collective
9871 
9872   Input Parameters:
9873 + A     - the matrix
9874 . P     - the projection matrix
9875 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9876 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9877           if the result is a dense matrix this is irrelevant
9878 
9879   Output Parameter:
9880 . C - the product matrix
9881 
9882   Level: intermediate
9883 
9884   Notes:
9885   C will be created and must be destroyed by the user with `MatDestroy()`.
9886 
9887   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9888 
9889   Developer Notes:
9890   For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9891 
9892 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9893 @*/
9894 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9895 {
9896   PetscFunctionBegin;
9897   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9898   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9899 
9900   if (scall == MAT_INITIAL_MATRIX) {
9901     PetscCall(MatProductCreate(A, P, NULL, C));
9902     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9903     PetscCall(MatProductSetAlgorithm(*C, "default"));
9904     PetscCall(MatProductSetFill(*C, fill));
9905 
9906     (*C)->product->api_user = PETSC_TRUE;
9907     PetscCall(MatProductSetFromOptions(*C));
9908     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);
9909     PetscCall(MatProductSymbolic(*C));
9910   } else { /* scall == MAT_REUSE_MATRIX */
9911     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9912   }
9913 
9914   PetscCall(MatProductNumeric(*C));
9915   (*C)->symmetric = A->symmetric;
9916   (*C)->spd       = A->spd;
9917   PetscFunctionReturn(PETSC_SUCCESS);
9918 }
9919 
9920 /*@
9921   MatRARt - Creates the matrix product C = R * A * R^T
9922 
9923   Neighbor-wise Collective
9924 
9925   Input Parameters:
9926 + A     - the matrix
9927 . R     - the projection matrix
9928 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9929 - fill  - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9930           if the result is a dense matrix this is irrelevant
9931 
9932   Output Parameter:
9933 . C - the product matrix
9934 
9935   Level: intermediate
9936 
9937   Notes:
9938   C will be created and must be destroyed by the user with `MatDestroy()`.
9939 
9940   An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9941 
9942   This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9943   which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9944   parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9945   We recommend using MatPtAP().
9946 
9947 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9948 @*/
9949 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9950 {
9951   PetscFunctionBegin;
9952   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9953   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9954 
9955   if (scall == MAT_INITIAL_MATRIX) {
9956     PetscCall(MatProductCreate(A, R, NULL, C));
9957     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9958     PetscCall(MatProductSetAlgorithm(*C, "default"));
9959     PetscCall(MatProductSetFill(*C, fill));
9960 
9961     (*C)->product->api_user = PETSC_TRUE;
9962     PetscCall(MatProductSetFromOptions(*C));
9963     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);
9964     PetscCall(MatProductSymbolic(*C));
9965   } else { /* scall == MAT_REUSE_MATRIX */
9966     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9967   }
9968 
9969   PetscCall(MatProductNumeric(*C));
9970   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9971   PetscFunctionReturn(PETSC_SUCCESS);
9972 }
9973 
9974 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9975 {
9976   PetscFunctionBegin;
9977   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9978 
9979   if (scall == MAT_INITIAL_MATRIX) {
9980     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9981     PetscCall(MatProductCreate(A, B, NULL, C));
9982     PetscCall(MatProductSetType(*C, ptype));
9983     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9984     PetscCall(MatProductSetFill(*C, fill));
9985 
9986     (*C)->product->api_user = PETSC_TRUE;
9987     PetscCall(MatProductSetFromOptions(*C));
9988     PetscCall(MatProductSymbolic(*C));
9989   } else { /* scall == MAT_REUSE_MATRIX */
9990     Mat_Product *product = (*C)->product;
9991     PetscBool    isdense;
9992 
9993     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9994     if (isdense && product && product->type != ptype) {
9995       PetscCall(MatProductClear(*C));
9996       product = NULL;
9997     }
9998     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9999     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
10000       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
10001       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
10002       product           = (*C)->product;
10003       product->fill     = fill;
10004       product->api_user = PETSC_TRUE;
10005       product->clear    = PETSC_TRUE;
10006 
10007       PetscCall(MatProductSetType(*C, ptype));
10008       PetscCall(MatProductSetFromOptions(*C));
10009       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);
10010       PetscCall(MatProductSymbolic(*C));
10011     } else { /* user may change input matrices A or B when REUSE */
10012       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10013     }
10014   }
10015   PetscCall(MatProductNumeric(*C));
10016   PetscFunctionReturn(PETSC_SUCCESS);
10017 }
10018 
10019 /*@
10020   MatMatMult - Performs matrix-matrix multiplication C=A*B.
10021 
10022   Neighbor-wise Collective
10023 
10024   Input Parameters:
10025 + A     - the left matrix
10026 . B     - the right matrix
10027 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10028 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10029           if the result is a dense matrix this is irrelevant
10030 
10031   Output Parameter:
10032 . C - the product matrix
10033 
10034   Notes:
10035   Unless scall is `MAT_REUSE_MATRIX` C will be created.
10036 
10037   `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
10038   call to this function with `MAT_INITIAL_MATRIX`.
10039 
10040   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10041 
10042   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`,
10043   rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10044 
10045   Example of Usage:
10046 .vb
10047      MatProductCreate(A,B,NULL,&C);
10048      MatProductSetType(C,MATPRODUCT_AB);
10049      MatProductSymbolic(C);
10050      MatProductNumeric(C); // compute C=A * B
10051      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10052      MatProductNumeric(C);
10053      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10054      MatProductNumeric(C);
10055 .ve
10056 
10057   Level: intermediate
10058 
10059 .seealso: [](ch_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10060 @*/
10061 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10062 {
10063   PetscFunctionBegin;
10064   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10065   PetscFunctionReturn(PETSC_SUCCESS);
10066 }
10067 
10068 /*@
10069   MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10070 
10071   Neighbor-wise Collective
10072 
10073   Input Parameters:
10074 + A     - the left matrix
10075 . B     - the right matrix
10076 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10077 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10078 
10079   Output Parameter:
10080 . C - the product matrix
10081 
10082   Level: intermediate
10083 
10084   Notes:
10085   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10086 
10087   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10088 
10089   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10090   actually needed.
10091 
10092   This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10093   and for pairs of `MATMPIDENSE` matrices.
10094 
10095   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10096 
10097   Options Database Keys:
10098 . -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10099               first redundantly copies the transposed B matrix on each process and requires O(log P) communication complexity;
10100               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10101 
10102 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductAlgorithm`, `MatProductType`
10103 @*/
10104 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10105 {
10106   PetscFunctionBegin;
10107   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10108   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10109   PetscFunctionReturn(PETSC_SUCCESS);
10110 }
10111 
10112 /*@
10113   MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10114 
10115   Neighbor-wise Collective
10116 
10117   Input Parameters:
10118 + A     - the left matrix
10119 . B     - the right matrix
10120 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10121 - fill  - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10122 
10123   Output Parameter:
10124 . C - the product matrix
10125 
10126   Level: intermediate
10127 
10128   Notes:
10129   C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10130 
10131   `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10132 
10133   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10134 
10135   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10136   actually needed.
10137 
10138   This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10139   which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10140 
10141 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10142 @*/
10143 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10144 {
10145   PetscFunctionBegin;
10146   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10147   PetscFunctionReturn(PETSC_SUCCESS);
10148 }
10149 
10150 /*@
10151   MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10152 
10153   Neighbor-wise Collective
10154 
10155   Input Parameters:
10156 + A     - the left matrix
10157 . B     - the middle matrix
10158 . C     - the right matrix
10159 . scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10160 - 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
10161           if the result is a dense matrix this is irrelevant
10162 
10163   Output Parameter:
10164 . D - the product matrix
10165 
10166   Level: intermediate
10167 
10168   Notes:
10169   Unless scall is `MAT_REUSE_MATRIX` D will be created.
10170 
10171   `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10172 
10173   This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10174 
10175   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10176   actually needed.
10177 
10178   If you have many matrices with the same non-zero structure to multiply, you
10179   should use `MAT_REUSE_MATRIX` in all calls but the first
10180 
10181 .seealso: [](ch_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10182 @*/
10183 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10184 {
10185   PetscFunctionBegin;
10186   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10187   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10188 
10189   if (scall == MAT_INITIAL_MATRIX) {
10190     PetscCall(MatProductCreate(A, B, C, D));
10191     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10192     PetscCall(MatProductSetAlgorithm(*D, "default"));
10193     PetscCall(MatProductSetFill(*D, fill));
10194 
10195     (*D)->product->api_user = PETSC_TRUE;
10196     PetscCall(MatProductSetFromOptions(*D));
10197     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,
10198                ((PetscObject)C)->type_name);
10199     PetscCall(MatProductSymbolic(*D));
10200   } else { /* user may change input matrices when REUSE */
10201     PetscCall(MatProductReplaceMats(A, B, C, *D));
10202   }
10203   PetscCall(MatProductNumeric(*D));
10204   PetscFunctionReturn(PETSC_SUCCESS);
10205 }
10206 
10207 /*@
10208   MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10209 
10210   Collective
10211 
10212   Input Parameters:
10213 + mat      - the matrix
10214 . nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10215 . subcomm  - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10216 - reuse    - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10217 
10218   Output Parameter:
10219 . matredundant - redundant matrix
10220 
10221   Level: advanced
10222 
10223   Notes:
10224   `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10225   original matrix has not changed from that last call to MatCreateRedundantMatrix().
10226 
10227   This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10228   calling it.
10229 
10230   `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10231 
10232 .seealso: [](ch_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubcomm`
10233 @*/
10234 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10235 {
10236   MPI_Comm       comm;
10237   PetscMPIInt    size;
10238   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10239   Mat_Redundant *redund     = NULL;
10240   PetscSubcomm   psubcomm   = NULL;
10241   MPI_Comm       subcomm_in = subcomm;
10242   Mat           *matseq;
10243   IS             isrow, iscol;
10244   PetscBool      newsubcomm = PETSC_FALSE;
10245 
10246   PetscFunctionBegin;
10247   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10248   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10249     PetscValidPointer(*matredundant, 5);
10250     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10251   }
10252 
10253   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10254   if (size == 1 || nsubcomm == 1) {
10255     if (reuse == MAT_INITIAL_MATRIX) {
10256       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10257     } else {
10258       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");
10259       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10260     }
10261     PetscFunctionReturn(PETSC_SUCCESS);
10262   }
10263 
10264   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10265   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10266   MatCheckPreallocated(mat, 1);
10267 
10268   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10269   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10270     /* create psubcomm, then get subcomm */
10271     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10272     PetscCallMPI(MPI_Comm_size(comm, &size));
10273     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10274 
10275     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10276     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10277     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10278     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10279     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10280     newsubcomm = PETSC_TRUE;
10281     PetscCall(PetscSubcommDestroy(&psubcomm));
10282   }
10283 
10284   /* get isrow, iscol and a local sequential matrix matseq[0] */
10285   if (reuse == MAT_INITIAL_MATRIX) {
10286     mloc_sub = PETSC_DECIDE;
10287     nloc_sub = PETSC_DECIDE;
10288     if (bs < 1) {
10289       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10290       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10291     } else {
10292       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10293       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10294     }
10295     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10296     rstart = rend - mloc_sub;
10297     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10298     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10299   } else { /* reuse == MAT_REUSE_MATRIX */
10300     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");
10301     /* retrieve subcomm */
10302     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10303     redund = (*matredundant)->redundant;
10304     isrow  = redund->isrow;
10305     iscol  = redund->iscol;
10306     matseq = redund->matseq;
10307   }
10308   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10309 
10310   /* get matredundant over subcomm */
10311   if (reuse == MAT_INITIAL_MATRIX) {
10312     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10313 
10314     /* create a supporting struct and attach it to C for reuse */
10315     PetscCall(PetscNew(&redund));
10316     (*matredundant)->redundant = redund;
10317     redund->isrow              = isrow;
10318     redund->iscol              = iscol;
10319     redund->matseq             = matseq;
10320     if (newsubcomm) {
10321       redund->subcomm = subcomm;
10322     } else {
10323       redund->subcomm = MPI_COMM_NULL;
10324     }
10325   } else {
10326     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10327   }
10328 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10329   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10330     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10331     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10332   }
10333 #endif
10334   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10335   PetscFunctionReturn(PETSC_SUCCESS);
10336 }
10337 
10338 /*@C
10339   MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10340   a given `Mat`. Each submatrix can span multiple procs.
10341 
10342   Collective
10343 
10344   Input Parameters:
10345 + mat     - the matrix
10346 . subComm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10347 - scall   - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10348 
10349   Output Parameter:
10350 . subMat - parallel sub-matrices each spanning a given `subcomm`
10351 
10352   Level: advanced
10353 
10354   Notes:
10355   The submatrix partition across processors is dictated by `subComm` a
10356   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10357   is not restricted to be grouped with consecutive original ranks.
10358 
10359   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10360   map directly to the layout of the original matrix [wrt the local
10361   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10362   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10363   the `subMat`. However the offDiagMat looses some columns - and this is
10364   reconstructed with `MatSetValues()`
10365 
10366   This is used by `PCBJACOBI` when a single block spans multiple MPI processes.
10367 
10368 .seealso: [](ch_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10369 @*/
10370 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10371 {
10372   PetscMPIInt commsize, subCommSize;
10373 
10374   PetscFunctionBegin;
10375   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10376   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10377   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10378 
10379   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");
10380   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10381   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10382   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10383   PetscFunctionReturn(PETSC_SUCCESS);
10384 }
10385 
10386 /*@
10387   MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10388 
10389   Not Collective
10390 
10391   Input Parameters:
10392 + mat   - matrix to extract local submatrix from
10393 . isrow - local row indices for submatrix
10394 - iscol - local column indices for submatrix
10395 
10396   Output Parameter:
10397 . submat - the submatrix
10398 
10399   Level: intermediate
10400 
10401   Notes:
10402   `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10403 
10404   Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10405   the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10406 
10407   `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10408   `MatSetValuesBlockedLocal()` will also be implemented.
10409 
10410   `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10411   Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10412 
10413 .seealso: [](ch_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10414 @*/
10415 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10416 {
10417   PetscFunctionBegin;
10418   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10419   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10420   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10421   PetscCheckSameComm(isrow, 2, iscol, 3);
10422   PetscValidPointer(submat, 4);
10423   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10424 
10425   if (mat->ops->getlocalsubmatrix) {
10426     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10427   } else {
10428     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10429   }
10430   PetscFunctionReturn(PETSC_SUCCESS);
10431 }
10432 
10433 /*@
10434   MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10435 
10436   Not Collective
10437 
10438   Input Parameters:
10439 + mat    - matrix to extract local submatrix from
10440 . isrow  - local row indices for submatrix
10441 . iscol  - local column indices for submatrix
10442 - submat - the submatrix
10443 
10444   Level: intermediate
10445 
10446 .seealso: [](ch_matrices), `Mat`, `MatGetLocalSubMatrix()`
10447 @*/
10448 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10449 {
10450   PetscFunctionBegin;
10451   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10452   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10453   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10454   PetscCheckSameComm(isrow, 2, iscol, 3);
10455   PetscValidPointer(submat, 4);
10456   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10457 
10458   if (mat->ops->restorelocalsubmatrix) {
10459     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10460   } else {
10461     PetscCall(MatDestroy(submat));
10462   }
10463   *submat = NULL;
10464   PetscFunctionReturn(PETSC_SUCCESS);
10465 }
10466 
10467 /*@
10468   MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10469 
10470   Collective
10471 
10472   Input Parameter:
10473 . mat - the matrix
10474 
10475   Output Parameter:
10476 . is - if any rows have zero diagonals this contains the list of them
10477 
10478   Level: developer
10479 
10480 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10481 @*/
10482 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10483 {
10484   PetscFunctionBegin;
10485   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10486   PetscValidType(mat, 1);
10487   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10488   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10489 
10490   if (!mat->ops->findzerodiagonals) {
10491     Vec                diag;
10492     const PetscScalar *a;
10493     PetscInt          *rows;
10494     PetscInt           rStart, rEnd, r, nrow = 0;
10495 
10496     PetscCall(MatCreateVecs(mat, &diag, NULL));
10497     PetscCall(MatGetDiagonal(mat, diag));
10498     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10499     PetscCall(VecGetArrayRead(diag, &a));
10500     for (r = 0; r < rEnd - rStart; ++r)
10501       if (a[r] == 0.0) ++nrow;
10502     PetscCall(PetscMalloc1(nrow, &rows));
10503     nrow = 0;
10504     for (r = 0; r < rEnd - rStart; ++r)
10505       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10506     PetscCall(VecRestoreArrayRead(diag, &a));
10507     PetscCall(VecDestroy(&diag));
10508     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10509   } else {
10510     PetscUseTypeMethod(mat, findzerodiagonals, is);
10511   }
10512   PetscFunctionReturn(PETSC_SUCCESS);
10513 }
10514 
10515 /*@
10516   MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10517 
10518   Collective
10519 
10520   Input Parameter:
10521 . mat - the matrix
10522 
10523   Output Parameter:
10524 . is - contains the list of rows with off block diagonal entries
10525 
10526   Level: developer
10527 
10528 .seealso: [](ch_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10529 @*/
10530 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10531 {
10532   PetscFunctionBegin;
10533   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10534   PetscValidType(mat, 1);
10535   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10536   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10537 
10538   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10539   PetscFunctionReturn(PETSC_SUCCESS);
10540 }
10541 
10542 /*@C
10543   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10544 
10545   Collective; No Fortran Support
10546 
10547   Input Parameter:
10548 . mat - the matrix
10549 
10550   Output Parameter:
10551 . values - the block inverses in column major order (FORTRAN-like)
10552 
10553   Level: advanced
10554 
10555   Notes:
10556   The size of the blocks is determined by the block size of the matrix.
10557 
10558   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10559 
10560   The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10561 
10562 .seealso: [](ch_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10563 @*/
10564 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10565 {
10566   PetscFunctionBegin;
10567   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10568   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10569   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10570   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10571   PetscFunctionReturn(PETSC_SUCCESS);
10572 }
10573 
10574 /*@C
10575   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10576 
10577   Collective; No Fortran Support
10578 
10579   Input Parameters:
10580 + mat     - the matrix
10581 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10582 - bsizes  - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10583 
10584   Output Parameter:
10585 . values - the block inverses in column major order (FORTRAN-like)
10586 
10587   Level: advanced
10588 
10589   Notes:
10590   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10591 
10592   The blocks never overlap between two MPI processes, use `MatInvertVariableBlockEnvelope()` for that case
10593 
10594 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10595 @*/
10596 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10597 {
10598   PetscFunctionBegin;
10599   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10600   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10601   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10602   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10603   PetscFunctionReturn(PETSC_SUCCESS);
10604 }
10605 
10606 /*@
10607   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10608 
10609   Collective
10610 
10611   Input Parameters:
10612 + A - the matrix
10613 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10614 
10615   Level: advanced
10616 
10617   Note:
10618   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10619 
10620 .seealso: [](ch_matrices), `Mat`, `MatInvertBlockDiagonal()`
10621 @*/
10622 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10623 {
10624   const PetscScalar *vals;
10625   PetscInt          *dnnz;
10626   PetscInt           m, rstart, rend, bs, i, j;
10627 
10628   PetscFunctionBegin;
10629   PetscCall(MatInvertBlockDiagonal(A, &vals));
10630   PetscCall(MatGetBlockSize(A, &bs));
10631   PetscCall(MatGetLocalSize(A, &m, NULL));
10632   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10633   PetscCall(PetscMalloc1(m / bs, &dnnz));
10634   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10635   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10636   PetscCall(PetscFree(dnnz));
10637   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10638   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10639   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10640   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10641   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10642   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10643   PetscFunctionReturn(PETSC_SUCCESS);
10644 }
10645 
10646 /*@C
10647   MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10648   via `MatTransposeColoringCreate()`.
10649 
10650   Collective
10651 
10652   Input Parameter:
10653 . c - coloring context
10654 
10655   Level: intermediate
10656 
10657 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`
10658 @*/
10659 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10660 {
10661   MatTransposeColoring matcolor = *c;
10662 
10663   PetscFunctionBegin;
10664   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10665   if (--((PetscObject)matcolor)->refct > 0) {
10666     matcolor = NULL;
10667     PetscFunctionReturn(PETSC_SUCCESS);
10668   }
10669 
10670   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10671   PetscCall(PetscFree(matcolor->rows));
10672   PetscCall(PetscFree(matcolor->den2sp));
10673   PetscCall(PetscFree(matcolor->colorforcol));
10674   PetscCall(PetscFree(matcolor->columns));
10675   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10676   PetscCall(PetscHeaderDestroy(c));
10677   PetscFunctionReturn(PETSC_SUCCESS);
10678 }
10679 
10680 /*@C
10681   MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10682   a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10683   `MatTransposeColoring` to sparse B.
10684 
10685   Collective
10686 
10687   Input Parameters:
10688 + coloring - coloring context created with `MatTransposeColoringCreate()`
10689 - B        - sparse matrix
10690 
10691   Output Parameter:
10692 . Btdense - dense matrix B^T
10693 
10694   Level: developer
10695 
10696   Note:
10697   These are used internally for some implementations of `MatRARt()`
10698 
10699 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10700 @*/
10701 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10702 {
10703   PetscFunctionBegin;
10704   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10705   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10706   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10707 
10708   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10709   PetscFunctionReturn(PETSC_SUCCESS);
10710 }
10711 
10712 /*@C
10713   MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10714   a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10715   in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10716   `Csp` from `Cden`.
10717 
10718   Collective
10719 
10720   Input Parameters:
10721 + matcoloring - coloring context created with `MatTransposeColoringCreate()`
10722 - Cden        - matrix product of a sparse matrix and a dense matrix Btdense
10723 
10724   Output Parameter:
10725 . Csp - sparse matrix
10726 
10727   Level: developer
10728 
10729   Note:
10730   These are used internally for some implementations of `MatRARt()`
10731 
10732 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10733 @*/
10734 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10735 {
10736   PetscFunctionBegin;
10737   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10738   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10739   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10740 
10741   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10742   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10743   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10744   PetscFunctionReturn(PETSC_SUCCESS);
10745 }
10746 
10747 /*@C
10748   MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10749 
10750   Collective
10751 
10752   Input Parameters:
10753 + mat        - the matrix product C
10754 - iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10755 
10756   Output Parameter:
10757 . color - the new coloring context
10758 
10759   Level: intermediate
10760 
10761 .seealso: [](ch_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10762           `MatTransColoringApplyDenToSp()`
10763 @*/
10764 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10765 {
10766   MatTransposeColoring c;
10767   MPI_Comm             comm;
10768 
10769   PetscFunctionBegin;
10770   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10771   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10772   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10773 
10774   c->ctype = iscoloring->ctype;
10775   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10776 
10777   *color = c;
10778   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10779   PetscFunctionReturn(PETSC_SUCCESS);
10780 }
10781 
10782 /*@
10783   MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10784   matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10785   same, otherwise it will be larger
10786 
10787   Not Collective
10788 
10789   Input Parameter:
10790 . mat - the matrix
10791 
10792   Output Parameter:
10793 . state - the current state
10794 
10795   Level: intermediate
10796 
10797   Notes:
10798   You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10799   different matrices
10800 
10801   Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10802 
10803   Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10804 
10805 .seealso: [](ch_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10806 @*/
10807 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10808 {
10809   PetscFunctionBegin;
10810   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10811   *state = mat->nonzerostate;
10812   PetscFunctionReturn(PETSC_SUCCESS);
10813 }
10814 
10815 /*@
10816   MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10817   matrices from each processor
10818 
10819   Collective
10820 
10821   Input Parameters:
10822 + comm   - the communicators the parallel matrix will live on
10823 . seqmat - the input sequential matrices
10824 . n      - number of local columns (or `PETSC_DECIDE`)
10825 - reuse  - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10826 
10827   Output Parameter:
10828 . mpimat - the parallel matrix generated
10829 
10830   Level: developer
10831 
10832   Note:
10833   The number of columns of the matrix in EACH processor MUST be the same.
10834 
10835 .seealso: [](ch_matrices), `Mat`
10836 @*/
10837 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10838 {
10839   PetscMPIInt size;
10840 
10841   PetscFunctionBegin;
10842   PetscCallMPI(MPI_Comm_size(comm, &size));
10843   if (size == 1) {
10844     if (reuse == MAT_INITIAL_MATRIX) {
10845       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10846     } else {
10847       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10848     }
10849     PetscFunctionReturn(PETSC_SUCCESS);
10850   }
10851 
10852   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");
10853 
10854   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10855   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10856   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10857   PetscFunctionReturn(PETSC_SUCCESS);
10858 }
10859 
10860 /*@
10861   MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent MPI ranks' ownership ranges.
10862 
10863   Collective
10864 
10865   Input Parameters:
10866 + A - the matrix to create subdomains from
10867 - N - requested number of subdomains
10868 
10869   Output Parameters:
10870 + n   - number of subdomains resulting on this MPI process
10871 - iss - `IS` list with indices of subdomains on this MPI process
10872 
10873   Level: advanced
10874 
10875   Note:
10876   The number of subdomains must be smaller than the communicator size
10877 
10878 .seealso: [](ch_matrices), `Mat`, `IS`
10879 @*/
10880 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10881 {
10882   MPI_Comm    comm, subcomm;
10883   PetscMPIInt size, rank, color;
10884   PetscInt    rstart, rend, k;
10885 
10886   PetscFunctionBegin;
10887   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10888   PetscCallMPI(MPI_Comm_size(comm, &size));
10889   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10890   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);
10891   *n    = 1;
10892   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10893   color = rank / k;
10894   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10895   PetscCall(PetscMalloc1(1, iss));
10896   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10897   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10898   PetscCallMPI(MPI_Comm_free(&subcomm));
10899   PetscFunctionReturn(PETSC_SUCCESS);
10900 }
10901 
10902 /*@
10903   MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10904 
10905   If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10906   If they are not the same, uses `MatMatMatMult()`.
10907 
10908   Once the coarse grid problem is constructed, correct for interpolation operators
10909   that are not of full rank, which can legitimately happen in the case of non-nested
10910   geometric multigrid.
10911 
10912   Input Parameters:
10913 + restrct     - restriction operator
10914 . dA          - fine grid matrix
10915 . interpolate - interpolation operator
10916 . reuse       - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10917 - fill        - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10918 
10919   Output Parameter:
10920 . A - the Galerkin coarse matrix
10921 
10922   Options Database Key:
10923 . -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10924 
10925   Level: developer
10926 
10927 .seealso: [](ch_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10928 @*/
10929 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10930 {
10931   IS  zerorows;
10932   Vec diag;
10933 
10934   PetscFunctionBegin;
10935   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10936   /* Construct the coarse grid matrix */
10937   if (interpolate == restrct) {
10938     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10939   } else {
10940     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10941   }
10942 
10943   /* If the interpolation matrix is not of full rank, A will have zero rows.
10944      This can legitimately happen in the case of non-nested geometric multigrid.
10945      In that event, we set the rows of the matrix to the rows of the identity,
10946      ignoring the equations (as the RHS will also be zero). */
10947 
10948   PetscCall(MatFindZeroRows(*A, &zerorows));
10949 
10950   if (zerorows != NULL) { /* if there are any zero rows */
10951     PetscCall(MatCreateVecs(*A, &diag, NULL));
10952     PetscCall(MatGetDiagonal(*A, diag));
10953     PetscCall(VecISSet(diag, zerorows, 1.0));
10954     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10955     PetscCall(VecDestroy(&diag));
10956     PetscCall(ISDestroy(&zerorows));
10957   }
10958   PetscFunctionReturn(PETSC_SUCCESS);
10959 }
10960 
10961 /*@C
10962   MatSetOperation - Allows user to set a matrix operation for any matrix type
10963 
10964   Logically Collective
10965 
10966   Input Parameters:
10967 + mat - the matrix
10968 . op  - the name of the operation
10969 - f   - the function that provides the operation
10970 
10971   Level: developer
10972 
10973   Usage:
10974 .vb
10975   extern PetscErrorCode usermult(Mat, Vec, Vec);
10976 
10977   PetscCall(MatCreateXXX(comm, ..., &A));
10978   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10979 .ve
10980 
10981   Notes:
10982   See the file `include/petscmat.h` for a complete list of matrix
10983   operations, which all have the form MATOP_<OPERATION>, where
10984   <OPERATION> is the name (in all capital letters) of the
10985   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10986 
10987   All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10988   sequence as the usual matrix interface routines, since they
10989   are intended to be accessed via the usual matrix interface
10990   routines, e.g.,
10991 .vb
10992   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10993 .ve
10994 
10995   In particular each function MUST return `PETSC_SUCCESS` on success and
10996   nonzero on failure.
10997 
10998   This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10999 
11000 .seealso: [](ch_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
11001 @*/
11002 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
11003 {
11004   PetscFunctionBegin;
11005   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11006   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
11007   (((void (**)(void))mat->ops)[op]) = f;
11008   PetscFunctionReturn(PETSC_SUCCESS);
11009 }
11010 
11011 /*@C
11012   MatGetOperation - Gets a matrix operation for any matrix type.
11013 
11014   Not Collective
11015 
11016   Input Parameters:
11017 + mat - the matrix
11018 - op  - the name of the operation
11019 
11020   Output Parameter:
11021 . f - the function that provides the operation
11022 
11023   Level: developer
11024 
11025   Usage:
11026 .vb
11027       PetscErrorCode (*usermult)(Mat, Vec, Vec);
11028       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
11029 .ve
11030 
11031   Notes:
11032   See the file include/petscmat.h for a complete list of matrix
11033   operations, which all have the form MATOP_<OPERATION>, where
11034   <OPERATION> is the name (in all capital letters) of the
11035   user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11036 
11037   This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11038 
11039 .seealso: [](ch_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11040 @*/
11041 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11042 {
11043   PetscFunctionBegin;
11044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11045   *f = (((void (**)(void))mat->ops)[op]);
11046   PetscFunctionReturn(PETSC_SUCCESS);
11047 }
11048 
11049 /*@
11050   MatHasOperation - Determines whether the given matrix supports the particular operation.
11051 
11052   Not Collective
11053 
11054   Input Parameters:
11055 + mat - the matrix
11056 - op  - the operation, for example, `MATOP_GET_DIAGONAL`
11057 
11058   Output Parameter:
11059 . has - either `PETSC_TRUE` or `PETSC_FALSE`
11060 
11061   Level: advanced
11062 
11063   Note:
11064   See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11065 
11066 .seealso: [](ch_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11067 @*/
11068 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11069 {
11070   PetscFunctionBegin;
11071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11072   PetscValidBoolPointer(has, 3);
11073   if (mat->ops->hasoperation) {
11074     PetscUseTypeMethod(mat, hasoperation, op, has);
11075   } else {
11076     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11077     else {
11078       *has = PETSC_FALSE;
11079       if (op == MATOP_CREATE_SUBMATRIX) {
11080         PetscMPIInt size;
11081 
11082         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11083         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11084       }
11085     }
11086   }
11087   PetscFunctionReturn(PETSC_SUCCESS);
11088 }
11089 
11090 /*@
11091   MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11092 
11093   Collective
11094 
11095   Input Parameter:
11096 . mat - the matrix
11097 
11098   Output Parameter:
11099 . cong - either `PETSC_TRUE` or `PETSC_FALSE`
11100 
11101   Level: beginner
11102 
11103 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11104 @*/
11105 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11106 {
11107   PetscFunctionBegin;
11108   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11109   PetscValidType(mat, 1);
11110   PetscValidBoolPointer(cong, 2);
11111   if (!mat->rmap || !mat->cmap) {
11112     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11113     PetscFunctionReturn(PETSC_SUCCESS);
11114   }
11115   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11116     PetscCall(PetscLayoutSetUp(mat->rmap));
11117     PetscCall(PetscLayoutSetUp(mat->cmap));
11118     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11119     if (*cong) mat->congruentlayouts = 1;
11120     else mat->congruentlayouts = 0;
11121   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11122   PetscFunctionReturn(PETSC_SUCCESS);
11123 }
11124 
11125 PetscErrorCode MatSetInf(Mat A)
11126 {
11127   PetscFunctionBegin;
11128   PetscUseTypeMethod(A, setinf);
11129   PetscFunctionReturn(PETSC_SUCCESS);
11130 }
11131 
11132 /*@C
11133   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
11134   and possibly removes small values from the graph structure.
11135 
11136   Collective
11137 
11138   Input Parameters:
11139 + A      - the matrix
11140 . sym    - `PETSC_TRUE` indicates that the graph should be symmetrized
11141 . scale  - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11142 - filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11143 
11144   Output Parameter:
11145 . graph - the resulting graph
11146 
11147   Level: advanced
11148 
11149 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11150 @*/
11151 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11152 {
11153   PetscFunctionBegin;
11154   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11155   PetscValidType(A, 1);
11156   PetscValidLogicalCollectiveBool(A, scale, 3);
11157   PetscValidPointer(graph, 5);
11158   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11159   PetscFunctionReturn(PETSC_SUCCESS);
11160 }
11161 
11162 /*@
11163   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11164   meaning the same memory is used for the matrix, and no new memory is allocated.
11165 
11166   Collective
11167 
11168   Input Parameter:
11169 . A - the matrix
11170 
11171   Level: intermediate
11172 
11173   Developer Notes:
11174   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11175   of the arrays in the data structure are unneeded.
11176 
11177 .seealso: [](ch_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11178 @*/
11179 PetscErrorCode MatEliminateZeros(Mat A)
11180 {
11181   PetscFunctionBegin;
11182   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11183   PetscUseTypeMethod(A, eliminatezeros);
11184   PetscFunctionReturn(PETSC_SUCCESS);
11185 }
11186