xref: /petsc/src/mat/interface/matrix.c (revision 48b2874ddef2e3516bb2759cc811cc96ed8aa65d) !
1 /*
2    This is where the abstract matrix operations are defined
3 */
4 
5 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
6 #include <petsc/private/isimpl.h>
7 #include <petsc/private/vecimpl.h>
8 
9 /* Logging support */
10 PetscClassId MAT_CLASSID;
11 PetscClassId MAT_COLORING_CLASSID;
12 PetscClassId MAT_FDCOLORING_CLASSID;
13 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
14 
15 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
16 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
17 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
18 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
19 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
20 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
21 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
22 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
23 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
24 PetscLogEvent MAT_TransposeColoringCreate;
25 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
26 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
27 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
28 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
29 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
30 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
31 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
32 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
33 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
34 PetscLogEvent MAT_GetMultiProcBlock;
35 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
36 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
37 PetscLogEvent MAT_SetValuesBatch;
38 PetscLogEvent MAT_ViennaCLCopyToGPU;
39 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
40 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
41 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
42 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
43 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
44 
45 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
46 
47 /*@
48    MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
49                   for sparse matrices that already have locations it fills the locations with random numbers
50 
51    Logically Collective on mat
52 
53    Input Parameters:
54 +  x  - the matrix
55 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and
56           it will create one internally.
57 
58    Output Parameter:
59 .  x  - the matrix
60 
61    Example of Usage:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68    Level: intermediate
69 
70 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
71 @*/
72 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) {
73   PetscRandom randObj = NULL;
74 
75   PetscFunctionBegin;
76   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
77   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
78   PetscValidType(x, 1);
79   MatCheckPreallocated(x, 1);
80 
81   if (!rctx) {
82     MPI_Comm comm;
83     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
84     PetscCall(PetscRandomCreate(comm, &randObj));
85     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
86     PetscCall(PetscRandomSetFromOptions(randObj));
87     rctx = randObj;
88   }
89   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
90   PetscUseTypeMethod(x, setrandom, rctx);
91   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
92 
93   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
94   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
95   PetscCall(PetscRandomDestroy(&randObj));
96   PetscFunctionReturn(0);
97 }
98 
99 /*@
100    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
101 
102    Logically Collective on mat
103 
104    Input Parameter:
105 .  mat - the factored matrix
106 
107    Output Parameters:
108 +  pivot - the pivot value computed
109 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
110          the share the matrix
111 
112    Level: advanced
113 
114    Notes:
115     This routine does not work for factorizations done with external packages.
116 
117     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
118 
119     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
120 
121 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
122           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
123 @*/
124 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) {
125   PetscFunctionBegin;
126   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
127   PetscValidRealPointer(pivot, 2);
128   PetscValidIntPointer(row, 3);
129   *pivot = mat->factorerror_zeropivot_value;
130   *row   = mat->factorerror_zeropivot_row;
131   PetscFunctionReturn(0);
132 }
133 
134 /*@
135    MatFactorGetError - gets the error code from a factorization
136 
137    Logically Collective on mat
138 
139    Input Parameters:
140 .  mat - the factored matrix
141 
142    Output Parameter:
143 .  err  - the error code
144 
145    Level: advanced
146 
147    Note:
148     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
149 
150 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
151           `MatFactorError`
152 @*/
153 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) {
154   PetscFunctionBegin;
155   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
156   PetscValidPointer(err, 2);
157   *err = mat->factorerrortype;
158   PetscFunctionReturn(0);
159 }
160 
161 /*@
162    MatFactorClearError - clears the error code in a factorization
163 
164    Logically Collective on mat
165 
166    Input Parameter:
167 .  mat - the factored matrix
168 
169    Level: developer
170 
171    Note:
172     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
173 
174 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
175           `MatGetErrorCode()`, `MatFactorError`
176 @*/
177 PetscErrorCode MatFactorClearError(Mat mat) {
178   PetscFunctionBegin;
179   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
180   mat->factorerrortype             = MAT_FACTOR_NOERROR;
181   mat->factorerror_zeropivot_value = 0.0;
182   mat->factorerror_zeropivot_row   = 0;
183   PetscFunctionReturn(0);
184 }
185 
186 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) {
187   Vec                r, l;
188   const PetscScalar *al;
189   PetscInt           i, nz, gnz, N, n;
190 
191   PetscFunctionBegin;
192   PetscCall(MatCreateVecs(mat, &r, &l));
193   if (!cols) { /* nonzero rows */
194     PetscCall(MatGetSize(mat, &N, NULL));
195     PetscCall(MatGetLocalSize(mat, &n, NULL));
196     PetscCall(VecSet(l, 0.0));
197     PetscCall(VecSetRandom(r, NULL));
198     PetscCall(MatMult(mat, r, l));
199     PetscCall(VecGetArrayRead(l, &al));
200   } else { /* nonzero columns */
201     PetscCall(MatGetSize(mat, NULL, &N));
202     PetscCall(MatGetLocalSize(mat, NULL, &n));
203     PetscCall(VecSet(r, 0.0));
204     PetscCall(VecSetRandom(l, NULL));
205     PetscCall(MatMultTranspose(mat, l, r));
206     PetscCall(VecGetArrayRead(r, &al));
207   }
208   if (tol <= 0.0) {
209     for (i = 0, nz = 0; i < n; i++)
210       if (al[i] != 0.0) nz++;
211   } else {
212     for (i = 0, nz = 0; i < n; i++)
213       if (PetscAbsScalar(al[i]) > tol) nz++;
214   }
215   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
216   if (gnz != N) {
217     PetscInt *nzr;
218     PetscCall(PetscMalloc1(nz, &nzr));
219     if (nz) {
220       if (tol < 0) {
221         for (i = 0, nz = 0; i < n; i++)
222           if (al[i] != 0.0) nzr[nz++] = i;
223       } else {
224         for (i = 0, nz = 0; i < n; i++)
225           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
226       }
227     }
228     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
229   } else *nonzero = NULL;
230   if (!cols) { /* nonzero rows */
231     PetscCall(VecRestoreArrayRead(l, &al));
232   } else {
233     PetscCall(VecRestoreArrayRead(r, &al));
234   }
235   PetscCall(VecDestroy(&l));
236   PetscCall(VecDestroy(&r));
237   PetscFunctionReturn(0);
238 }
239 
240 /*@
241       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
242 
243   Input Parameter:
244 .    A  - the matrix
245 
246   Output Parameter:
247 .    keptrows - the rows that are not completely zero
248 
249   Note:
250     keptrows is set to NULL if all rows are nonzero.
251 
252   Level: intermediate
253 
254 .seealso: `Mat`, `MatFindZeroRows()`
255  @*/
256 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) {
257   PetscFunctionBegin;
258   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
259   PetscValidType(mat, 1);
260   PetscValidPointer(keptrows, 2);
261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
262   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
263   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
264   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
265   PetscFunctionReturn(0);
266 }
267 
268 /*@
269       MatFindZeroRows - Locate all rows that are completely zero in the matrix
270 
271   Input Parameter:
272 .    A  - the matrix
273 
274   Output Parameter:
275 .    zerorows - the rows that are completely zero
276 
277   Note:
278     zerorows is set to NULL if no rows are zero.
279 
280   Level: intermediate
281 
282 .seealso: `Mat`, `MatFindNonzeroRows()`
283  @*/
284 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) {
285   IS       keptrows;
286   PetscInt m, n;
287 
288   PetscFunctionBegin;
289   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
290   PetscValidType(mat, 1);
291   PetscValidPointer(zerorows, 2);
292   PetscCall(MatFindNonzeroRows(mat, &keptrows));
293   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
294      In keeping with this convention, we set zerorows to NULL if there are no zero
295      rows. */
296   if (keptrows == NULL) {
297     *zerorows = NULL;
298   } else {
299     PetscCall(MatGetOwnershipRange(mat, &m, &n));
300     PetscCall(ISComplement(keptrows, m, n, zerorows));
301     PetscCall(ISDestroy(&keptrows));
302   }
303   PetscFunctionReturn(0);
304 }
305 
306 /*@
307    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
308 
309    Not Collective
310 
311    Input Parameters:
312 .   A - the matrix
313 
314    Output Parameters:
315 .   a - the diagonal part (which is a SEQUENTIAL matrix)
316 
317    Notes:
318    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
319 
320    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation.
321 
322    Level: advanced
323 
324 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
325 @*/
326 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) {
327   PetscFunctionBegin;
328   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
329   PetscValidType(A, 1);
330   PetscValidPointer(a, 2);
331   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
332   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
333   else {
334     PetscMPIInt size;
335 
336     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
337     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
338     *a = A;
339   }
340   PetscFunctionReturn(0);
341 }
342 
343 /*@
344    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
345 
346    Collective on mat
347 
348    Input Parameters:
349 .  mat - the matrix
350 
351    Output Parameter:
352 .   trace - the sum of the diagonal entries
353 
354    Level: advanced
355 
356 .seealso: `Mat`
357 @*/
358 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) {
359   Vec diag;
360 
361   PetscFunctionBegin;
362   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
363   PetscValidScalarPointer(trace, 2);
364   PetscCall(MatCreateVecs(mat, &diag, NULL));
365   PetscCall(MatGetDiagonal(mat, diag));
366   PetscCall(VecSum(diag, trace));
367   PetscCall(VecDestroy(&diag));
368   PetscFunctionReturn(0);
369 }
370 
371 /*@
372    MatRealPart - Zeros out the imaginary part of the matrix
373 
374    Logically Collective on mat
375 
376    Input Parameters:
377 .  mat - the matrix
378 
379    Level: advanced
380 
381 .seealso: `MatImaginaryPart()`
382 @*/
383 PetscErrorCode MatRealPart(Mat mat) {
384   PetscFunctionBegin;
385   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
386   PetscValidType(mat, 1);
387   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
388   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
389   MatCheckPreallocated(mat, 1);
390   PetscUseTypeMethod(mat, realpart);
391   PetscFunctionReturn(0);
392 }
393 
394 /*@C
395    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
396 
397    Collective on mat
398 
399    Input Parameter:
400 .  mat - the matrix
401 
402    Output Parameters:
403 +   nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
404 -   ghosts - the global indices of the ghost points
405 
406    Note:
407     the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
408 
409    Level: advanced
410 
411 .seealso: `Mat`, `VecCreateGhost()`
412 @*/
413 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) {
414   PetscFunctionBegin;
415   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
416   PetscValidType(mat, 1);
417   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
418   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
419   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
420   else {
421     if (nghosts) *nghosts = 0;
422     if (ghosts) *ghosts = NULL;
423   }
424   PetscFunctionReturn(0);
425 }
426 
427 /*@
428    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
429 
430    Logically Collective on mat
431 
432    Input Parameters:
433 .  mat - the matrix
434 
435    Level: advanced
436 
437 .seealso: `MatRealPart()`
438 @*/
439 PetscErrorCode MatImaginaryPart(Mat mat) {
440   PetscFunctionBegin;
441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
442   PetscValidType(mat, 1);
443   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
444   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
445   MatCheckPreallocated(mat, 1);
446   PetscUseTypeMethod(mat, imaginarypart);
447   PetscFunctionReturn(0);
448 }
449 
450 /*@
451    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
452 
453    Not Collective
454 
455    Input Parameter:
456 .  mat - the matrix
457 
458    Output Parameters:
459 +  missing - is any diagonal missing
460 -  dd - first diagonal entry that is missing (optional) on this process
461 
462    Level: advanced
463 
464 .seealso: `Mat`
465 @*/
466 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) {
467   PetscFunctionBegin;
468   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
469   PetscValidType(mat, 1);
470   PetscValidBoolPointer(missing, 2);
471   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
472   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
473   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
474   PetscFunctionReturn(0);
475 }
476 
477 /*@C
478    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
479    for each row that you get to ensure that your application does
480    not bleed memory.
481 
482    Not Collective
483 
484    Input Parameters:
485 +  mat - the matrix
486 -  row - the row to get
487 
488    Output Parameters:
489 +  ncols -  if not NULL, the number of nonzeros in the row
490 .  cols - if not NULL, the column numbers
491 -  vals - if not NULL, the values
492 
493    Notes:
494    This routine is provided for people who need to have direct access
495    to the structure of a matrix.  We hope that we provide enough
496    high-level matrix routines that few users will need it.
497 
498    `MatGetRow()` always returns 0-based column indices, regardless of
499    whether the internal representation is 0-based (default) or 1-based.
500 
501    For better efficiency, set cols and/or vals to NULL if you do
502    not wish to extract these quantities.
503 
504    The user can only examine the values extracted with `MatGetRow()`;
505    the values cannot be altered.  To change the matrix entries, one
506    must use `MatSetValues()`.
507 
508    You can only have one call to `MatGetRow()` outstanding for a particular
509    matrix at a time, per processor. `MatGetRow()` can only obtain rows
510    associated with the given processor, it cannot get rows from the
511    other processors; for that we suggest using `MatCreateSubMatrices()`, then
512    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
513    is in the global number of rows.
514 
515    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
516 
517    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
518 
519    Fortran Note:
520    The calling sequence from Fortran is
521 .vb
522    MatGetRow(matrix,row,ncols,cols,values,ierr)
523          Mat     matrix (input)
524          integer row    (input)
525          integer ncols  (output)
526          integer cols(maxcols) (output)
527          double precision (or double complex) values(maxcols) output
528 .ve
529    where maxcols >= maximum nonzeros in any row of the matrix.
530 
531    Caution:
532    Do not try to change the contents of the output arrays (cols and vals).
533    In some cases, this may corrupt the matrix.
534 
535    Level: advanced
536 
537 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
538 @*/
539 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) {
540   PetscInt incols;
541 
542   PetscFunctionBegin;
543   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
544   PetscValidType(mat, 1);
545   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
546   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
547   MatCheckPreallocated(mat, 1);
548   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);
549   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
550   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
551   if (ncols) *ncols = incols;
552   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
553   PetscFunctionReturn(0);
554 }
555 
556 /*@
557    MatConjugate - replaces the matrix values with their complex conjugates
558 
559    Logically Collective on mat
560 
561    Input Parameters:
562 .  mat - the matrix
563 
564    Level: advanced
565 
566 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
567 @*/
568 PetscErrorCode MatConjugate(Mat mat) {
569   PetscFunctionBegin;
570   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
571   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
572   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
573     PetscUseTypeMethod(mat, conjugate);
574     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
575   }
576   PetscFunctionReturn(0);
577 }
578 
579 /*@C
580    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
581 
582    Not Collective
583 
584    Input Parameters:
585 +  mat - the matrix
586 .  row - the row to get
587 .  ncols, cols - the number of nonzeros and their columns
588 -  vals - if nonzero the column values
589 
590    Notes:
591    This routine should be called after you have finished examining the entries.
592 
593    This routine zeros out ncols, cols, and vals. This is to prevent accidental
594    us of the array after it has been restored. If you pass NULL, it will
595    not zero the pointers.  Use of cols or vals after `MatRestoreRow()` is invalid.
596 
597    Fortran Notes:
598    The calling sequence from Fortran is
599 .vb
600    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
601       Mat     matrix (input)
602       integer row    (input)
603       integer ncols  (output)
604       integer cols(maxcols) (output)
605       double precision (or double complex) values(maxcols) output
606 .ve
607    Where maxcols >= maximum nonzeros in any row of the matrix.
608 
609    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
610    before another call to `MatGetRow()` can be made.
611 
612    Level: advanced
613 
614 .seealso: `MatGetRow()`
615 @*/
616 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) {
617   PetscFunctionBegin;
618   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
619   if (ncols) PetscValidIntPointer(ncols, 3);
620   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
621   if (!mat->ops->restorerow) PetscFunctionReturn(0);
622   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
623   if (ncols) *ncols = 0;
624   if (cols) *cols = NULL;
625   if (vals) *vals = NULL;
626   PetscFunctionReturn(0);
627 }
628 
629 /*@
630    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
631    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
632 
633    Not Collective
634 
635    Input Parameters:
636 .  mat - the matrix
637 
638    Note:
639    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.
640 
641    Level: advanced
642 
643 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
644 @*/
645 PetscErrorCode MatGetRowUpperTriangular(Mat mat) {
646   PetscFunctionBegin;
647   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
648   PetscValidType(mat, 1);
649   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
650   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
651   MatCheckPreallocated(mat, 1);
652   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
653   PetscUseTypeMethod(mat, getrowuppertriangular);
654   PetscFunctionReturn(0);
655 }
656 
657 /*@
658    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
659 
660    Not Collective
661 
662    Input Parameters:
663 .  mat - the matrix
664 
665    Note:
666    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
667 
668    Level: advanced
669 
670 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
671 @*/
672 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) {
673   PetscFunctionBegin;
674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
675   PetscValidType(mat, 1);
676   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
677   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
678   MatCheckPreallocated(mat, 1);
679   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
680   PetscUseTypeMethod(mat, restorerowuppertriangular);
681   PetscFunctionReturn(0);
682 }
683 
684 /*@C
685    MatSetOptionsPrefix - Sets the prefix used for searching for all
686    `Mat` options in the database.
687 
688    Logically Collective on A
689 
690    Input Parameters:
691 +  A - the matrix
692 -  prefix - the prefix to prepend to all option names
693 
694    Notes:
695    A hyphen (-) must NOT be given at the beginning of the prefix name.
696    The first character of all runtime options is AUTOMATICALLY the hyphen.
697 
698    This is NOT used for options for the factorization of the matrix. Normally the
699    prefix is automatically passed in from the PC calling the factorization. To set
700    it directly use  `MatSetOptionsPrefixFactor()`
701 
702    Level: advanced
703 
704 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
705 @*/
706 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) {
707   PetscFunctionBegin;
708   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
709   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
710   PetscFunctionReturn(0);
711 }
712 
713 /*@C
714    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
715    for matrices created with `MatGetFactor()`
716 
717    Logically Collective on A
718 
719    Input Parameters:
720 +  A - the matrix
721 -  prefix - the prefix to prepend to all option names for the factored matrix
722 
723    Notes:
724    A hyphen (-) must NOT be given at the beginning of the prefix name.
725    The first character of all runtime options is AUTOMATICALLY the hyphen.
726 
727    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
728    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
729 
730    Level: developer
731 
732 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
733 @*/
734 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) {
735   PetscFunctionBegin;
736   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
737   if (prefix) {
738     PetscValidCharPointer(prefix, 2);
739     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
740     if (prefix != A->factorprefix) {
741       PetscCall(PetscFree(A->factorprefix));
742       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
743     }
744   } else PetscCall(PetscFree(A->factorprefix));
745   PetscFunctionReturn(0);
746 }
747 
748 /*@C
749    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
750    for matrices created with `MatGetFactor()`
751 
752    Logically Collective on A
753 
754    Input Parameters:
755 +  A - the matrix
756 -  prefix - the prefix to prepend to all option names for the factored matrix
757 
758    Notes:
759    A hyphen (-) must NOT be given at the beginning of the prefix name.
760    The first character of all runtime options is AUTOMATICALLY the hyphen.
761 
762    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
763    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
764 
765    Level: developer
766 
767 .seealso: `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
768              `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
769              `MatSetOptionsPrefix()`
770 @*/
771 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) {
772   char  *buf = A->factorprefix;
773   size_t len1, len2;
774 
775   PetscFunctionBegin;
776   PetscValidHeader(A, 1);
777   if (!prefix) PetscFunctionReturn(0);
778   if (!buf) {
779     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
780     PetscFunctionReturn(0);
781   }
782   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
783 
784   PetscCall(PetscStrlen(prefix, &len1));
785   PetscCall(PetscStrlen(buf, &len2));
786   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
787   PetscCall(PetscStrcpy(A->factorprefix, buf));
788   PetscCall(PetscStrcat(A->factorprefix, prefix));
789   PetscCall(PetscFree(buf));
790   PetscFunctionReturn(0);
791 }
792 
793 /*@C
794    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
795    matrix options in the database.
796 
797    Logically Collective on A
798 
799    Input Parameters:
800 +  A - the matrix
801 -  prefix - the prefix to prepend to all option names
802 
803    Note:
804    A hyphen (-) must NOT be given at the beginning of the prefix name.
805    The first character of all runtime options is AUTOMATICALLY the hyphen.
806 
807    Level: advanced
808 
809 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
810 @*/
811 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) {
812   PetscFunctionBegin;
813   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
814   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
815   PetscFunctionReturn(0);
816 }
817 
818 /*@C
819    MatGetOptionsPrefix - Gets the prefix used for searching for all
820    matrix options in the database.
821 
822    Not Collective
823 
824    Input Parameter:
825 .  A - the matrix
826 
827    Output Parameter:
828 .  prefix - pointer to the prefix string used
829 
830    Fortran Note:
831     On the fortran side, the user should pass in a string 'prefix' of
832    sufficient length to hold the prefix.
833 
834    Level: advanced
835 
836 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
837 @*/
838 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscValidPointer(prefix, 2);
842   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
843   PetscFunctionReturn(0);
844 }
845 
846 /*@
847    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
848 
849    Collective on A
850 
851    Input Parameters:
852 .  A - the matrix
853 
854    Notes:
855    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
856 
857    Users can reset the preallocation to access the original memory.
858 
859    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.
860 
861    Level: beginner
862 
863 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
864 @*/
865 PetscErrorCode MatResetPreallocation(Mat A) {
866   PetscFunctionBegin;
867   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
868   PetscValidType(A, 1);
869   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
870   PetscFunctionReturn(0);
871 }
872 
873 /*@
874    MatSetUp - Sets up the internal matrix data structures for later use.
875 
876    Collective on A
877 
878    Input Parameters:
879 .  A - the matrix
880 
881    Notes:
882    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
883 
884    If a suitable preallocation routine is used, this function does not need to be called.
885 
886    See the Performance chapter of the PETSc users manual for how to preallocate matrices
887 
888    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
889 
890    Level: intermediate
891 
892 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
893 @*/
894 PetscErrorCode MatSetUp(Mat A) {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   if (!((PetscObject)A)->type_name) {
898     PetscMPIInt size;
899 
900     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
901     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
902   }
903   if (!A->preallocated && A->ops->setup) {
904     PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n"));
905     PetscUseTypeMethod(A, setup);
906   }
907   PetscCall(PetscLayoutSetUp(A->rmap));
908   PetscCall(PetscLayoutSetUp(A->cmap));
909   A->preallocated = PETSC_TRUE;
910   PetscFunctionReturn(0);
911 }
912 
913 #if defined(PETSC_HAVE_SAWS)
914 #include <petscviewersaws.h>
915 #endif
916 
917 /*@C
918    MatViewFromOptions - View properties of the matrix from the options database
919 
920    Collective on A
921 
922    Input Parameters:
923 +  A - the matrix
924 .  obj - optional additional object that provides the options prefix to use
925 -  name - command line option
926 
927   Options Database:
928 .  -mat_view [viewertype]:... - the viewer and its options
929 
930   Notes:
931 .vb
932     If no value is provided ascii:stdout is used
933        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
934                                                   for example ascii::ascii_info prints just the information about the object not all details
935                                                   unless :append is given filename opens in write mode, overwriting what was already there
936        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
937        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
938        socket[:port]                             defaults to the standard output port
939        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
940 .ve
941 
942    Level: intermediate
943 
944 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
945 @*/
946 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) {
947   PetscFunctionBegin;
948   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
949   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
950   PetscFunctionReturn(0);
951 }
952 
953 /*@C
954    MatView - display information about a matrix in a variety ways
955 
956    Collective on mat
957 
958    Input Parameters:
959 +  mat - the matrix
960 -  viewer - visualization context
961 
962   Notes:
963   The available visualization contexts include
964 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
965 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
966 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
967 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
968 
969    The user can open alternative visualization contexts with
970 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
971 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
972          specified file; corresponding input uses MatLoad()
973 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
974          an X window display
975 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
976          Currently only the sequential dense and AIJ
977          matrix types support the Socket viewer.
978 
979    The user can call `PetscViewerPushFormat()` to specify the output
980    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
981    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
982 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
983 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
984 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
985 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
986          format common among all matrix types
987 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
988          format (which is in many cases the same as the default)
989 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
990          size and structure (not the matrix entries)
991 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
992          the matrix structure
993 
994    Options Database Keys:
995 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
996 .  -mat_view ::ascii_info_detail - Prints more detailed info
997 .  -mat_view - Prints matrix in ASCII format
998 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
999 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1000 .  -display <name> - Sets display name (default is host)
1001 .  -draw_pause <sec> - Sets number of seconds to pause after display
1002 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1003 .  -viewer_socket_machine <machine> -
1004 .  -viewer_socket_port <port> -
1005 .  -mat_view binary - save matrix to file in binary format
1006 -  -viewer_binary_filename <name> -
1007 
1008    Level: beginner
1009 
1010    Notes:
1011     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1012     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1013 
1014     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1015 
1016     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1017       viewer is used.
1018 
1019       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1020       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1021 
1022       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1023       and then use the following mouse functions.
1024 .vb
1025   left mouse: zoom in
1026   middle mouse: zoom out
1027   right mouse: continue with the simulation
1028 .ve
1029 
1030 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`,
1031           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1032 @*/
1033 PetscErrorCode MatView(Mat mat, PetscViewer viewer) {
1034   PetscInt          rows, cols, rbs, cbs;
1035   PetscBool         isascii, isstring, issaws;
1036   PetscViewerFormat format;
1037   PetscMPIInt       size;
1038 
1039   PetscFunctionBegin;
1040   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1041   PetscValidType(mat, 1);
1042   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1043   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1044   PetscCheckSameComm(mat, 1, viewer, 2);
1045   MatCheckPreallocated(mat, 1);
1046 
1047   PetscCall(PetscViewerGetFormat(viewer, &format));
1048   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1049   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1050 
1051   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1052   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1053   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1054   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");
1055 
1056   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1057   if (isascii) {
1058     PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Must call MatAssemblyBegin/End() before viewing matrix");
1059     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1060     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1061       MatNullSpace nullsp, transnullsp;
1062 
1063       PetscCall(PetscViewerASCIIPushTab(viewer));
1064       PetscCall(MatGetSize(mat, &rows, &cols));
1065       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1066       if (rbs != 1 || cbs != 1) {
1067         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1068         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1069       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1070       if (mat->factortype) {
1071         MatSolverType solver;
1072         PetscCall(MatFactorGetSolverType(mat, &solver));
1073         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1074       }
1075       if (mat->ops->getinfo) {
1076         MatInfo info;
1077         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1078         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1079         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1080       }
1081       PetscCall(MatGetNullSpace(mat, &nullsp));
1082       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1083       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1084       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1085       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1086       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1087       PetscCall(PetscViewerASCIIPushTab(viewer));
1088       PetscCall(MatProductView(mat, viewer));
1089       PetscCall(PetscViewerASCIIPopTab(viewer));
1090     }
1091   } else if (issaws) {
1092 #if defined(PETSC_HAVE_SAWS)
1093     PetscMPIInt rank;
1094 
1095     PetscCall(PetscObjectName((PetscObject)mat));
1096     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1097     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1098 #endif
1099   } else if (isstring) {
1100     const char *type;
1101     PetscCall(MatGetType(mat, &type));
1102     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1103     PetscTryTypeMethod(mat, view, viewer);
1104   }
1105   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1106     PetscCall(PetscViewerASCIIPushTab(viewer));
1107     PetscUseTypeMethod(mat, viewnative, viewer);
1108     PetscCall(PetscViewerASCIIPopTab(viewer));
1109   } else if (mat->ops->view) {
1110     PetscCall(PetscViewerASCIIPushTab(viewer));
1111     PetscUseTypeMethod(mat, view, viewer);
1112     PetscCall(PetscViewerASCIIPopTab(viewer));
1113   }
1114   if (isascii) {
1115     PetscCall(PetscViewerGetFormat(viewer, &format));
1116     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1117   }
1118   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1119   PetscFunctionReturn(0);
1120 }
1121 
1122 #if defined(PETSC_USE_DEBUG)
1123 #include <../src/sys/totalview/tv_data_display.h>
1124 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) {
1125   TV_add_row("Local rows", "int", &mat->rmap->n);
1126   TV_add_row("Local columns", "int", &mat->cmap->n);
1127   TV_add_row("Global rows", "int", &mat->rmap->N);
1128   TV_add_row("Global columns", "int", &mat->cmap->N);
1129   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1130   return TV_format_OK;
1131 }
1132 #endif
1133 
1134 /*@C
1135    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1136    with `MatView()`.  The matrix format is determined from the options database.
1137    Generates a parallel MPI matrix if the communicator has more than one
1138    processor.  The default matrix type is `MATAIJ`.
1139 
1140    Collective on mat
1141 
1142    Input Parameters:
1143 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1144             or some related function before a call to `MatLoad()`
1145 -  viewer - binary/HDF5 file viewer
1146 
1147    Options Database Keys:
1148    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1149    block size
1150 .    -matload_block_size <bs> - set block size
1151 
1152    Level: beginner
1153 
1154    Notes:
1155    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1156    `Mat` before calling this routine if you wish to set it from the options database.
1157 
1158    `MatLoad()` automatically loads into the options database any options
1159    given in the file filename.info where filename is the name of the file
1160    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1161    file will be ignored if you use the -viewer_binary_skip_info option.
1162 
1163    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1164    sets the default matrix type AIJ and sets the local and global sizes.
1165    If type and/or size is already set, then the same are used.
1166 
1167    In parallel, each processor can load a subset of rows (or the
1168    entire matrix).  This routine is especially useful when a large
1169    matrix is stored on disk and only part of it is desired on each
1170    processor.  For example, a parallel solver may access only some of
1171    the rows from each processor.  The algorithm used here reads
1172    relatively small blocks of data rather than reading the entire
1173    matrix and then subsetting it.
1174 
1175    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1176    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1177    or the sequence like
1178 .vb
1179     `PetscViewer` v;
1180     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1181     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1182     `PetscViewerSetFromOptions`(v);
1183     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1184     `PetscViewerFileSetName`(v,"datafile");
1185 .ve
1186    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1187 $ -viewer_type {binary,hdf5}
1188 
1189    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1190    and src/mat/tutorials/ex10.c with the second approach.
1191 
1192    Notes about the PETSc binary format:
1193    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1194    is read onto rank 0 and then shipped to its destination rank, one after another.
1195    Multiple objects, both matrices and vectors, can be stored within the same file.
1196    Their PetscObject name is ignored; they are loaded in the order of their storage.
1197 
1198    Most users should not need to know the details of the binary storage
1199    format, since `MatLoad()` and `MatView()` completely hide these details.
1200    But for anyone who's interested, the standard binary matrix storage
1201    format is
1202 
1203 $    PetscInt    MAT_FILE_CLASSID
1204 $    PetscInt    number of rows
1205 $    PetscInt    number of columns
1206 $    PetscInt    total number of nonzeros
1207 $    PetscInt    *number nonzeros in each row
1208 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1209 $    PetscScalar *values of all nonzeros
1210 
1211    PETSc automatically does the byte swapping for
1212 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1213 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1214 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1215 and `PetscBinaryWrite()` to see how this may be done.
1216 
1217    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1218    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1219    Each processor's chunk is loaded independently by its owning rank.
1220    Multiple objects, both matrices and vectors, can be stored within the same file.
1221    They are looked up by their PetscObject name.
1222 
1223    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1224    by default the same structure and naming of the AIJ arrays and column count
1225    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1226 $    save example.mat A b -v7.3
1227    can be directly read by this routine (see Reference 1 for details).
1228    Note that depending on your MATLAB version, this format might be a default,
1229    otherwise you can set it as default in Preferences.
1230 
1231    Unless -nocompression flag is used to save the file in MATLAB,
1232    PETSc must be configured with ZLIB package.
1233 
1234    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1235 
1236    Current HDF5 (MAT-File) limitations:
1237    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1238 
1239    Corresponding `MatView()` is not yet implemented.
1240 
1241    The loaded matrix is actually a transpose of the original one in MATLAB,
1242    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1243    With this format, matrix is automatically transposed by PETSc,
1244    unless the matrix is marked as SPD or symmetric
1245    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1246 
1247    References:
1248 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1249 
1250 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1251  @*/
1252 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) {
1253   PetscBool flg;
1254 
1255   PetscFunctionBegin;
1256   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1257   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1258 
1259   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1260 
1261   flg = PETSC_FALSE;
1262   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1263   if (flg) {
1264     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1265     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1266   }
1267   flg = PETSC_FALSE;
1268   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1269   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1270 
1271   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1272   PetscUseTypeMethod(mat, load, viewer);
1273   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1274   PetscFunctionReturn(0);
1275 }
1276 
1277 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) {
1278   Mat_Redundant *redund = *redundant;
1279 
1280   PetscFunctionBegin;
1281   if (redund) {
1282     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1283       PetscCall(ISDestroy(&redund->isrow));
1284       PetscCall(ISDestroy(&redund->iscol));
1285       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1286     } else {
1287       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1288       PetscCall(PetscFree(redund->sbuf_j));
1289       PetscCall(PetscFree(redund->sbuf_a));
1290       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1291         PetscCall(PetscFree(redund->rbuf_j[i]));
1292         PetscCall(PetscFree(redund->rbuf_a[i]));
1293       }
1294       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1295     }
1296 
1297     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1298     PetscCall(PetscFree(redund));
1299   }
1300   PetscFunctionReturn(0);
1301 }
1302 
1303 /*@C
1304    MatDestroy - Frees space taken by a matrix.
1305 
1306    Collective on A
1307 
1308    Input Parameter:
1309 .  A - the matrix
1310 
1311    Level: beginner
1312 
1313    Developer Note:
1314    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1315    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1316    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1317    if changes are needed here.
1318 
1319 .seealso: `Mat`, `MatCreate()`
1320 @*/
1321 PetscErrorCode MatDestroy(Mat *A) {
1322   PetscFunctionBegin;
1323   if (!*A) PetscFunctionReturn(0);
1324   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1325   if (--((PetscObject)(*A))->refct > 0) {
1326     *A = NULL;
1327     PetscFunctionReturn(0);
1328   }
1329 
1330   /* if memory was published with SAWs then destroy it */
1331   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1332   PetscTryTypeMethod((*A), destroy);
1333 
1334   PetscCall(PetscFree((*A)->factorprefix));
1335   PetscCall(PetscFree((*A)->defaultvectype));
1336   PetscCall(PetscFree((*A)->defaultrandtype));
1337   PetscCall(PetscFree((*A)->bsizes));
1338   PetscCall(PetscFree((*A)->solvertype));
1339   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1340   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1341   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1342   PetscCall(MatProductClear(*A));
1343   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1344   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1345   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1346   PetscCall(MatDestroy(&(*A)->schur));
1347   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1348   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1349   PetscCall(PetscHeaderDestroy(A));
1350   PetscFunctionReturn(0);
1351 }
1352 
1353 /*@C
1354    MatSetValues - Inserts or adds a block of values into a matrix.
1355    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1356    MUST be called after all calls to `MatSetValues()` have been completed.
1357 
1358    Not Collective
1359 
1360    Input Parameters:
1361 +  mat - the matrix
1362 .  v - a logically two-dimensional array of values
1363 .  m, idxm - the number of rows and their global indices
1364 .  n, idxn - the number of columns and their global indices
1365 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1366 
1367    Notes:
1368    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1369       `MatSetUp()` before using this routine
1370 
1371    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1372 
1373    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1374    options cannot be mixed without intervening calls to the assembly
1375    routines.
1376 
1377    `MatSetValues()` uses 0-based row and column numbers in Fortran
1378    as well as in C.
1379 
1380    Negative indices may be passed in idxm and idxn, these rows and columns are
1381    simply ignored. This allows easily inserting element stiffness matrices
1382    with homogeneous Dirchlet boundary conditions that you don't want represented
1383    in the matrix.
1384 
1385    Efficiency Alert:
1386    The routine `MatSetValuesBlocked()` may offer much better efficiency
1387    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1388 
1389    Level: beginner
1390 
1391    Developer Note:
1392    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1393    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1394 
1395 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1396           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1397 @*/
1398 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) {
1399   PetscFunctionBeginHot;
1400   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1401   PetscValidType(mat, 1);
1402   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1403   PetscValidIntPointer(idxm, 3);
1404   PetscValidIntPointer(idxn, 5);
1405   MatCheckPreallocated(mat, 1);
1406 
1407   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1408   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1409 
1410   if (PetscDefined(USE_DEBUG)) {
1411     PetscInt i, j;
1412 
1413     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1414     for (i = 0; i < m; i++) {
1415       for (j = 0; j < n; j++) {
1416         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1417 #if defined(PETSC_USE_COMPLEX)
1418           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]);
1419 #else
1420           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]);
1421 #endif
1422       }
1423     }
1424     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);
1425     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);
1426   }
1427 
1428   if (mat->assembled) {
1429     mat->was_assembled = PETSC_TRUE;
1430     mat->assembled     = PETSC_FALSE;
1431   }
1432   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1433   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1434   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1435   PetscFunctionReturn(0);
1436 }
1437 
1438 /*@C
1439    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1440    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1441    MUST be called after all calls to `MatSetValues()` have been completed.
1442 
1443    Not Collective
1444 
1445    Input Parameters:
1446 +  mat - the matrix
1447 .  v - a logically two-dimensional array of values
1448 .  ism - the rows to provide
1449 .  isn - the columns to provide
1450 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1451 
1452    Notes:
1453    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1454       `MatSetUp()` before using this routine
1455 
1456    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1457 
1458    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1459    options cannot be mixed without intervening calls to the assembly
1460    routines.
1461 
1462    MatSetValues() uses 0-based row and column numbers in Fortran
1463    as well as in C.
1464 
1465    Negative indices may be passed in ism and isn, these rows and columns are
1466    simply ignored. This allows easily inserting element stiffness matrices
1467    with homogeneous Dirchlet boundary conditions that you don't want represented
1468    in the matrix.
1469 
1470    Efficiency Alert:
1471    The routine `MatSetValuesBlocked()` may offer much better efficiency
1472    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1473 
1474    Level: beginner
1475 
1476    Developer Notes:
1477     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1478                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1479 
1480     This is currently not optimized for any particular `ISType`
1481 
1482 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1483           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1484 @*/
1485 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) {
1486   PetscInt        m, n;
1487   const PetscInt *rows, *cols;
1488 
1489   PetscFunctionBeginHot;
1490   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1491   PetscCall(ISGetIndices(ism, &rows));
1492   PetscCall(ISGetIndices(isn, &cols));
1493   PetscCall(ISGetLocalSize(ism, &m));
1494   PetscCall(ISGetLocalSize(isn, &n));
1495   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1496   PetscCall(ISRestoreIndices(ism, &rows));
1497   PetscCall(ISRestoreIndices(isn, &cols));
1498   PetscFunctionReturn(0);
1499 }
1500 
1501 /*@
1502    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1503         values into a matrix
1504 
1505    Not Collective
1506 
1507    Input Parameters:
1508 +  mat - the matrix
1509 .  row - the (block) row to set
1510 -  v - a logically two-dimensional array of values
1511 
1512    Notes:
1513    By the values, v, are column-oriented (for the block version) and sorted
1514 
1515    All the nonzeros in the row must be provided
1516 
1517    The matrix must have previously had its column indices set
1518 
1519    The row must belong to this process
1520 
1521    Level: intermediate
1522 
1523 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1524           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1525 @*/
1526 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) {
1527   PetscInt globalrow;
1528 
1529   PetscFunctionBegin;
1530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1531   PetscValidType(mat, 1);
1532   PetscValidScalarPointer(v, 3);
1533   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1534   PetscCall(MatSetValuesRow(mat, globalrow, v));
1535   PetscFunctionReturn(0);
1536 }
1537 
1538 /*@
1539    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1540         values into a matrix
1541 
1542    Not Collective
1543 
1544    Input Parameters:
1545 +  mat - the matrix
1546 .  row - the (block) row to set
1547 -  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
1548 
1549    Notes:
1550    The values, v, are column-oriented for the block version.
1551 
1552    All the nonzeros in the row must be provided
1553 
1554    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1555 
1556    The row must belong to this process
1557 
1558    Level: advanced
1559 
1560 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1561           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1562 @*/
1563 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) {
1564   PetscFunctionBeginHot;
1565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1566   PetscValidType(mat, 1);
1567   MatCheckPreallocated(mat, 1);
1568   PetscValidScalarPointer(v, 3);
1569   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1570   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1571   mat->insertmode = INSERT_VALUES;
1572 
1573   if (mat->assembled) {
1574     mat->was_assembled = PETSC_TRUE;
1575     mat->assembled     = PETSC_FALSE;
1576   }
1577   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1578   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1579   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1580   PetscFunctionReturn(0);
1581 }
1582 
1583 /*@
1584    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1585      Using structured grid indexing
1586 
1587    Not Collective
1588 
1589    Input Parameters:
1590 +  mat - the matrix
1591 .  m - number of rows being entered
1592 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1593 .  n - number of columns being entered
1594 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1595 .  v - a logically two-dimensional array of values
1596 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1597 
1598    Notes:
1599    By default the values, v, are row-oriented.  See `MatSetOption()` for other options.
1600 
1601    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1602    options cannot be mixed without intervening calls to the assembly
1603    routines.
1604 
1605    The grid coordinates are across the entire grid, not just the local portion
1606 
1607    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1608    as well as in C.
1609 
1610    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1611 
1612    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1613    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1614 
1615    The columns and rows in the stencil passed in MUST be contained within the
1616    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1617    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1618    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1619    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1620 
1621    In Fortran idxm and idxn should be declared as
1622 $     MatStencil idxm(4,m),idxn(4,n)
1623    and the values inserted using
1624 $    idxm(MatStencil_i,1) = i
1625 $    idxm(MatStencil_j,1) = j
1626 $    idxm(MatStencil_k,1) = k
1627 $    idxm(MatStencil_c,1) = c
1628    etc
1629 
1630    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1631    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1632    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1633    `DM_BOUNDARY_PERIODIC` boundary type.
1634 
1635    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
1636    a single value per point) you can skip filling those indices.
1637 
1638    Inspired by the structured grid interface to the HYPRE package
1639    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1640 
1641    Efficiency Alert:
1642    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1643    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1644 
1645    Level: beginner
1646 
1647 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1648           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1649 @*/
1650 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) {
1651   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1652   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1653   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1654 
1655   PetscFunctionBegin;
1656   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1657   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1658   PetscValidType(mat, 1);
1659   PetscValidPointer(idxm, 3);
1660   PetscValidPointer(idxn, 5);
1661 
1662   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1663     jdxm = buf;
1664     jdxn = buf + m;
1665   } else {
1666     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1667     jdxm = bufm;
1668     jdxn = bufn;
1669   }
1670   for (i = 0; i < m; i++) {
1671     for (j = 0; j < 3 - sdim; j++) dxm++;
1672     tmp = *dxm++ - starts[0];
1673     for (j = 0; j < dim - 1; j++) {
1674       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1675       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1676     }
1677     if (mat->stencil.noc) dxm++;
1678     jdxm[i] = tmp;
1679   }
1680   for (i = 0; i < n; i++) {
1681     for (j = 0; j < 3 - sdim; j++) dxn++;
1682     tmp = *dxn++ - starts[0];
1683     for (j = 0; j < dim - 1; j++) {
1684       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1685       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1686     }
1687     if (mat->stencil.noc) dxn++;
1688     jdxn[i] = tmp;
1689   }
1690   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1691   PetscCall(PetscFree2(bufm, bufn));
1692   PetscFunctionReturn(0);
1693 }
1694 
1695 /*@
1696    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1697      Using structured grid indexing
1698 
1699    Not Collective
1700 
1701    Input Parameters:
1702 +  mat - the matrix
1703 .  m - number of rows being entered
1704 .  idxm - grid coordinates for matrix rows being entered
1705 .  n - number of columns being entered
1706 .  idxn - grid coordinates for matrix columns being entered
1707 .  v - a logically two-dimensional array of values
1708 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1709 
1710    Notes:
1711    By default the values, v, are row-oriented and unsorted.
1712    See `MatSetOption()` for other options.
1713 
1714    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1715    options cannot be mixed without intervening calls to the assembly
1716    routines.
1717 
1718    The grid coordinates are across the entire grid, not just the local portion
1719 
1720    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1721    as well as in C.
1722 
1723    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1724 
1725    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1726    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1727 
1728    The columns and rows in the stencil passed in MUST be contained within the
1729    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1730    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1731    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1732    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1733 
1734    In Fortran idxm and idxn should be declared as
1735 $     MatStencil idxm(4,m),idxn(4,n)
1736    and the values inserted using
1737 $    idxm(MatStencil_i,1) = i
1738 $    idxm(MatStencil_j,1) = j
1739 $    idxm(MatStencil_k,1) = k
1740    etc
1741 
1742    Negative indices may be passed in idxm and idxn, these rows and columns are
1743    simply ignored. This allows easily inserting element stiffness matrices
1744    with homogeneous Dirchlet boundary conditions that you don't want represented
1745    in the matrix.
1746 
1747    Inspired by the structured grid interface to the HYPRE package
1748    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1749 
1750    Level: beginner
1751 
1752 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1753           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1754           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1755 @*/
1756 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) {
1757   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1758   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1759   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1760 
1761   PetscFunctionBegin;
1762   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1763   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1764   PetscValidType(mat, 1);
1765   PetscValidPointer(idxm, 3);
1766   PetscValidPointer(idxn, 5);
1767   PetscValidScalarPointer(v, 6);
1768 
1769   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1770     jdxm = buf;
1771     jdxn = buf + m;
1772   } else {
1773     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1774     jdxm = bufm;
1775     jdxn = bufn;
1776   }
1777   for (i = 0; i < m; i++) {
1778     for (j = 0; j < 3 - sdim; j++) dxm++;
1779     tmp = *dxm++ - starts[0];
1780     for (j = 0; j < sdim - 1; j++) {
1781       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1782       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1783     }
1784     dxm++;
1785     jdxm[i] = tmp;
1786   }
1787   for (i = 0; i < n; i++) {
1788     for (j = 0; j < 3 - sdim; j++) dxn++;
1789     tmp = *dxn++ - starts[0];
1790     for (j = 0; j < sdim - 1; j++) {
1791       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1792       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1793     }
1794     dxn++;
1795     jdxn[i] = tmp;
1796   }
1797   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1798   PetscCall(PetscFree2(bufm, bufn));
1799   PetscFunctionReturn(0);
1800 }
1801 
1802 /*@
1803    MatSetStencil - Sets the grid information for setting values into a matrix via
1804         `MatSetValuesStencil()`
1805 
1806    Not Collective
1807 
1808    Input Parameters:
1809 +  mat - the matrix
1810 .  dim - dimension of the grid 1, 2, or 3
1811 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1812 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1813 -  dof - number of degrees of freedom per node
1814 
1815    Notes:
1816    Inspired by the structured grid interface to the HYPRE package
1817    (www.llnl.gov/CASC/hyper)
1818 
1819    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1820    user.
1821 
1822    Level: beginner
1823 
1824 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1825           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1826 @*/
1827 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) {
1828   PetscFunctionBegin;
1829   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1830   PetscValidIntPointer(dims, 3);
1831   PetscValidIntPointer(starts, 4);
1832 
1833   mat->stencil.dim = dim + (dof > 1);
1834   for (PetscInt i = 0; i < dim; i++) {
1835     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1836     mat->stencil.starts[i] = starts[dim - i - 1];
1837   }
1838   mat->stencil.dims[dim]   = dof;
1839   mat->stencil.starts[dim] = 0;
1840   mat->stencil.noc         = (PetscBool)(dof == 1);
1841   PetscFunctionReturn(0);
1842 }
1843 
1844 /*@C
1845    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1846 
1847    Not Collective
1848 
1849    Input Parameters:
1850 +  mat - the matrix
1851 .  v - a logically two-dimensional array of values
1852 .  m, idxm - the number of block rows and their global block indices
1853 .  n, idxn - the number of block columns and their global block indices
1854 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1855 
1856    Notes:
1857    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1858    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1859 
1860    The m and n count the NUMBER of blocks in the row direction and column direction,
1861    NOT the total number of rows/columns; for example, if the block size is 2 and
1862    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1863    The values in idxm would be 1 2; that is the first index for each block divided by
1864    the block size.
1865 
1866    Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1867    preallocating it).
1868 
1869    By default the values, v, are row-oriented, so the layout of
1870    v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1871 
1872    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1873    options cannot be mixed without intervening calls to the assembly
1874    routines.
1875 
1876    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1877    as well as in C.
1878 
1879    Negative indices may be passed in idxm and idxn, these rows and columns are
1880    simply ignored. This allows easily inserting element stiffness matrices
1881    with homogeneous Dirchlet boundary conditions that you don't want represented
1882    in the matrix.
1883 
1884    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1885    internal searching must be done to determine where to place the
1886    data in the matrix storage space.  By instead inserting blocks of
1887    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1888    reduced.
1889 
1890    Example:
1891 $   Suppose m=n=2 and block size(bs) = 2 The array is
1892 $
1893 $   1  2  | 3  4
1894 $   5  6  | 7  8
1895 $   - - - | - - -
1896 $   9  10 | 11 12
1897 $   13 14 | 15 16
1898 $
1899 $   v[] should be passed in like
1900 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1901 $
1902 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1903 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1904 
1905    Level: intermediate
1906 
1907 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1908 @*/
1909 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) {
1910   PetscFunctionBeginHot;
1911   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1912   PetscValidType(mat, 1);
1913   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1914   PetscValidIntPointer(idxm, 3);
1915   PetscValidIntPointer(idxn, 5);
1916   MatCheckPreallocated(mat, 1);
1917   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1918   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1919   if (PetscDefined(USE_DEBUG)) {
1920     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1921     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1922   }
1923   if (PetscDefined(USE_DEBUG)) {
1924     PetscInt rbs, cbs, M, N, i;
1925     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1926     PetscCall(MatGetSize(mat, &M, &N));
1927     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);
1928     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);
1929   }
1930   if (mat->assembled) {
1931     mat->was_assembled = PETSC_TRUE;
1932     mat->assembled     = PETSC_FALSE;
1933   }
1934   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1935   if (mat->ops->setvaluesblocked) {
1936     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1937   } else {
1938     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1939     PetscInt i, j, bs, cbs;
1940 
1941     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1942     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1943       iidxm = buf;
1944       iidxn = buf + m * bs;
1945     } else {
1946       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1947       iidxm = bufr;
1948       iidxn = bufc;
1949     }
1950     for (i = 0; i < m; i++) {
1951       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1952     }
1953     if (m != n || bs != cbs || idxm != idxn) {
1954       for (i = 0; i < n; i++) {
1955         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1956       }
1957     } else iidxn = iidxm;
1958     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
1959     PetscCall(PetscFree2(bufr, bufc));
1960   }
1961   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1962   PetscFunctionReturn(0);
1963 }
1964 
1965 /*@C
1966    MatGetValues - Gets a block of local values from a matrix.
1967 
1968    Not Collective; can only return values that are owned by the give process
1969 
1970    Input Parameters:
1971 +  mat - the matrix
1972 .  v - a logically two-dimensional array for storing the values
1973 .  m, idxm - the number of rows and their global indices
1974 -  n, idxn - the number of columns and their global indices
1975 
1976    Notes:
1977      The user must allocate space (m*n `PetscScalar`s) for the values, v.
1978      The values, v, are then returned in a row-oriented format,
1979      analogous to that used by default in `MatSetValues()`.
1980 
1981      `MatGetValues()` uses 0-based row and column numbers in
1982      Fortran as well as in C.
1983 
1984      `MatGetValues()` requires that the matrix has been assembled
1985      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
1986      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
1987      without intermediate matrix assembly.
1988 
1989      Negative row or column indices will be ignored and those locations in v[] will be
1990      left unchanged.
1991 
1992      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
1993      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
1994      from `MatGetOwnershipRange`(mat,&rstart,&rend).
1995 
1996    Level: advanced
1997 
1998 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
1999 @*/
2000 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) {
2001   PetscFunctionBegin;
2002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2003   PetscValidType(mat, 1);
2004   if (!m || !n) PetscFunctionReturn(0);
2005   PetscValidIntPointer(idxm, 3);
2006   PetscValidIntPointer(idxn, 5);
2007   PetscValidScalarPointer(v, 6);
2008   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2009   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2010   MatCheckPreallocated(mat, 1);
2011 
2012   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2013   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2014   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2015   PetscFunctionReturn(0);
2016 }
2017 
2018 /*@C
2019    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2020      defined previously by `MatSetLocalToGlobalMapping()`
2021 
2022    Not Collective
2023 
2024    Input Parameters:
2025 +  mat - the matrix
2026 .  nrow, irow - number of rows and their local indices
2027 -  ncol, icol - number of columns and their local indices
2028 
2029    Output Parameter:
2030 .  y -  a logically two-dimensional array of values
2031 
2032    Notes:
2033      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2034 
2035      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2036      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2037      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2038      with `MatSetLocalToGlobalMapping()`.
2039 
2040    Developer Note:
2041       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2042       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2043 
2044    Level: advanced
2045 
2046 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2047           `MatSetValuesLocal()`, `MatGetValues()`
2048 @*/
2049 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) {
2050   PetscFunctionBeginHot;
2051   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2052   PetscValidType(mat, 1);
2053   MatCheckPreallocated(mat, 1);
2054   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2055   PetscValidIntPointer(irow, 3);
2056   PetscValidIntPointer(icol, 5);
2057   if (PetscDefined(USE_DEBUG)) {
2058     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2059     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2060   }
2061   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2062   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2063   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2064   else {
2065     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2066     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2067       irowm = buf;
2068       icolm = buf + nrow;
2069     } else {
2070       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2071       irowm = bufr;
2072       icolm = bufc;
2073     }
2074     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2075     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2076     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2077     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2078     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2079     PetscCall(PetscFree2(bufr, bufc));
2080   }
2081   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2082   PetscFunctionReturn(0);
2083 }
2084 
2085 /*@
2086   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2087   the same size. Currently, this can only be called once and creates the given matrix.
2088 
2089   Not Collective
2090 
2091   Input Parameters:
2092 + mat - the matrix
2093 . nb - the number of blocks
2094 . bs - the number of rows (and columns) in each block
2095 . rows - a concatenation of the rows for each block
2096 - v - a concatenation of logically two-dimensional arrays of values
2097 
2098   Note:
2099   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2100 
2101   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2102 
2103   Level: advanced
2104 
2105 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2106           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2107 @*/
2108 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) {
2109   PetscFunctionBegin;
2110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2111   PetscValidType(mat, 1);
2112   PetscValidIntPointer(rows, 4);
2113   PetscValidScalarPointer(v, 5);
2114   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2115 
2116   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2117   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2118   else {
2119     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2120   }
2121   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2122   PetscFunctionReturn(0);
2123 }
2124 
2125 /*@
2126    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2127    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2128    using a local (per-processor) numbering.
2129 
2130    Not Collective
2131 
2132    Input Parameters:
2133 +  x - the matrix
2134 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2135 -  cmapping - column mapping
2136 
2137    Level: intermediate
2138 
2139    Note:
2140    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2141 
2142 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2143 @*/
2144 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) {
2145   PetscFunctionBegin;
2146   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2147   PetscValidType(x, 1);
2148   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2149   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2150   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2151   else {
2152     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2153     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2154   }
2155   PetscFunctionReturn(0);
2156 }
2157 
2158 /*@
2159    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2160 
2161    Not Collective
2162 
2163    Input Parameter:
2164 .  A - the matrix
2165 
2166    Output Parameters:
2167 + rmapping - row mapping
2168 - cmapping - column mapping
2169 
2170    Level: advanced
2171 
2172 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2173 @*/
2174 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) {
2175   PetscFunctionBegin;
2176   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2177   PetscValidType(A, 1);
2178   if (rmapping) {
2179     PetscValidPointer(rmapping, 2);
2180     *rmapping = A->rmap->mapping;
2181   }
2182   if (cmapping) {
2183     PetscValidPointer(cmapping, 3);
2184     *cmapping = A->cmap->mapping;
2185   }
2186   PetscFunctionReturn(0);
2187 }
2188 
2189 /*@
2190    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2191 
2192    Logically Collective on A
2193 
2194    Input Parameters:
2195 +  A - the matrix
2196 . rmap - row layout
2197 - cmap - column layout
2198 
2199    Level: advanced
2200 
2201    Note:
2202    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2203 
2204 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2205 @*/
2206 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) {
2207   PetscFunctionBegin;
2208   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2209   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2210   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2211   PetscFunctionReturn(0);
2212 }
2213 
2214 /*@
2215    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2216 
2217    Not Collective
2218 
2219    Input Parameter:
2220 .  A - the matrix
2221 
2222    Output Parameters:
2223 + rmap - row layout
2224 - cmap - column layout
2225 
2226    Level: advanced
2227 
2228 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2229 @*/
2230 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) {
2231   PetscFunctionBegin;
2232   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2233   PetscValidType(A, 1);
2234   if (rmap) {
2235     PetscValidPointer(rmap, 2);
2236     *rmap = A->rmap;
2237   }
2238   if (cmap) {
2239     PetscValidPointer(cmap, 3);
2240     *cmap = A->cmap;
2241   }
2242   PetscFunctionReturn(0);
2243 }
2244 
2245 /*@C
2246    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2247    using a local numbering of the nodes.
2248 
2249    Not Collective
2250 
2251    Input Parameters:
2252 +  mat - the matrix
2253 .  nrow, irow - number of rows and their local indices
2254 .  ncol, icol - number of columns and their local indices
2255 .  y -  a logically two-dimensional array of values
2256 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2257 
2258    Notes:
2259    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2260       `MatSetUp()` before using this routine
2261 
2262    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2263 
2264    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2265    options cannot be mixed without intervening calls to the assembly
2266    routines.
2267 
2268    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2269    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2270 
2271    Level: intermediate
2272 
2273    Developer Note:
2274     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2275                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2276 
2277 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2278           `MatGetValuesLocal()`
2279 @*/
2280 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) {
2281   PetscFunctionBeginHot;
2282   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2283   PetscValidType(mat, 1);
2284   MatCheckPreallocated(mat, 1);
2285   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2286   PetscValidIntPointer(irow, 3);
2287   PetscValidIntPointer(icol, 5);
2288   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2289   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2290   if (PetscDefined(USE_DEBUG)) {
2291     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2292     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2293   }
2294 
2295   if (mat->assembled) {
2296     mat->was_assembled = PETSC_TRUE;
2297     mat->assembled     = PETSC_FALSE;
2298   }
2299   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2300   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2301   else {
2302     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2303     const PetscInt *irowm, *icolm;
2304 
2305     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2306       bufr  = buf;
2307       bufc  = buf + nrow;
2308       irowm = bufr;
2309       icolm = bufc;
2310     } else {
2311       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2312       irowm = bufr;
2313       icolm = bufc;
2314     }
2315     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2316     else irowm = irow;
2317     if (mat->cmap->mapping) {
2318       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2319         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2320       } else icolm = irowm;
2321     } else icolm = icol;
2322     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2323     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2324   }
2325   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2326   PetscFunctionReturn(0);
2327 }
2328 
2329 /*@C
2330    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2331    using a local ordering of the nodes a block at a time.
2332 
2333    Not Collective
2334 
2335    Input Parameters:
2336 +  x - the matrix
2337 .  nrow, irow - number of rows and their local indices
2338 .  ncol, icol - number of columns and their local indices
2339 .  y -  a logically two-dimensional array of values
2340 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2341 
2342    Notes:
2343    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2344       `MatSetUp()` before using this routine
2345 
2346    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2347       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2348 
2349    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2350    options cannot be mixed without intervening calls to the assembly
2351    routines.
2352 
2353    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2354    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2355 
2356    Level: intermediate
2357 
2358    Developer Note:
2359     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2360                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2361 
2362 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2363           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2364 @*/
2365 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) {
2366   PetscFunctionBeginHot;
2367   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2368   PetscValidType(mat, 1);
2369   MatCheckPreallocated(mat, 1);
2370   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2371   PetscValidIntPointer(irow, 3);
2372   PetscValidIntPointer(icol, 5);
2373   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2374   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2375   if (PetscDefined(USE_DEBUG)) {
2376     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2377     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);
2378   }
2379 
2380   if (mat->assembled) {
2381     mat->was_assembled = PETSC_TRUE;
2382     mat->assembled     = PETSC_FALSE;
2383   }
2384   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2385     PetscInt irbs, rbs;
2386     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2387     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2388     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2389   }
2390   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2391     PetscInt icbs, cbs;
2392     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2393     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2394     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2395   }
2396   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2397   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2398   else {
2399     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2400     const PetscInt *irowm, *icolm;
2401 
2402     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2403       bufr  = buf;
2404       bufc  = buf + nrow;
2405       irowm = bufr;
2406       icolm = bufc;
2407     } else {
2408       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2409       irowm = bufr;
2410       icolm = bufc;
2411     }
2412     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2413     else irowm = irow;
2414     if (mat->cmap->mapping) {
2415       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2416         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2417       } else icolm = irowm;
2418     } else icolm = icol;
2419     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2420     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2421   }
2422   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2423   PetscFunctionReturn(0);
2424 }
2425 
2426 /*@
2427    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2428 
2429    Collective on mat
2430 
2431    Input Parameters:
2432 +  mat - the matrix
2433 -  x   - the vector to be multiplied
2434 
2435    Output Parameters:
2436 .  y - the result
2437 
2438    Note:
2439    The vectors x and y cannot be the same.  I.e., one cannot
2440    call `MatMultDiagonalBlock`(A,y,y).
2441 
2442    Level: developer
2443 
2444 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2445 @*/
2446 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) {
2447   PetscFunctionBegin;
2448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2449   PetscValidType(mat, 1);
2450   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2451   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2452 
2453   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2454   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2455   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2456   MatCheckPreallocated(mat, 1);
2457 
2458   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2459   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2460   PetscFunctionReturn(0);
2461 }
2462 
2463 /* --------------------------------------------------------*/
2464 /*@
2465    MatMult - Computes the matrix-vector product, y = Ax.
2466 
2467    Neighbor-wise Collective on mat
2468 
2469    Input Parameters:
2470 +  mat - the matrix
2471 -  x   - the vector to be multiplied
2472 
2473    Output Parameters:
2474 .  y - the result
2475 
2476    Note:
2477    The vectors x and y cannot be the same.  I.e., one cannot
2478    call `MatMult`(A,y,y).
2479 
2480    Level: beginner
2481 
2482 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2483 @*/
2484 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) {
2485   PetscFunctionBegin;
2486   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2487   PetscValidType(mat, 1);
2488   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2489   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2492   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2493   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);
2494   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);
2495   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);
2496   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);
2497   PetscCall(VecSetErrorIfLocked(y, 3));
2498   if (mat->erroriffailure) PetscCall(VecValidValues(x, 2, PETSC_TRUE));
2499   MatCheckPreallocated(mat, 1);
2500 
2501   PetscCall(VecLockReadPush(x));
2502   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2503   PetscUseTypeMethod(mat, mult, x, y);
2504   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2505   if (mat->erroriffailure) PetscCall(VecValidValues(y, 3, PETSC_FALSE));
2506   PetscCall(VecLockReadPop(x));
2507   PetscFunctionReturn(0);
2508 }
2509 
2510 /*@
2511    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2512 
2513    Neighbor-wise Collective on mat
2514 
2515    Input Parameters:
2516 +  mat - the matrix
2517 -  x   - the vector to be multiplied
2518 
2519    Output Parameters:
2520 .  y - the result
2521 
2522    Notes:
2523    The vectors x and y cannot be the same.  I.e., one cannot
2524    call `MatMultTranspose`(A,y,y).
2525 
2526    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2527    use `MatMultHermitianTranspose()`
2528 
2529    Level: beginner
2530 
2531 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2532 @*/
2533 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) {
2534   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2535 
2536   PetscFunctionBegin;
2537   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2538   PetscValidType(mat, 1);
2539   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2540   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2541 
2542   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2543   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2544   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2545   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);
2546   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);
2547   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);
2548   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);
2549   if (mat->erroriffailure) PetscCall(VecValidValues(x, 2, PETSC_TRUE));
2550   MatCheckPreallocated(mat, 1);
2551 
2552   if (!mat->ops->multtranspose) {
2553     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2554     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);
2555   } else op = mat->ops->multtranspose;
2556   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2557   PetscCall(VecLockReadPush(x));
2558   PetscCall((*op)(mat, x, y));
2559   PetscCall(VecLockReadPop(x));
2560   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2561   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2562   if (mat->erroriffailure) PetscCall(VecValidValues(y, 3, PETSC_FALSE));
2563   PetscFunctionReturn(0);
2564 }
2565 
2566 /*@
2567    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2568 
2569    Neighbor-wise Collective on mat
2570 
2571    Input Parameters:
2572 +  mat - the matrix
2573 -  x   - the vector to be multilplied
2574 
2575    Output Parameters:
2576 .  y - the result
2577 
2578    Notes:
2579    The vectors x and y cannot be the same.  I.e., one cannot
2580    call `MatMultHermitianTranspose`(A,y,y).
2581 
2582    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2583 
2584    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2585 
2586    Level: beginner
2587 
2588 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2589 @*/
2590 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) {
2591   PetscFunctionBegin;
2592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2593   PetscValidType(mat, 1);
2594   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2595   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2596 
2597   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2598   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2599   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2600   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);
2601   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);
2602   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);
2603   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);
2604   MatCheckPreallocated(mat, 1);
2605 
2606   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2607 #if defined(PETSC_USE_COMPLEX)
2608   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2609     PetscCall(VecLockReadPush(x));
2610     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2611     else PetscUseTypeMethod(mat, mult, x, y);
2612     PetscCall(VecLockReadPop(x));
2613   } else {
2614     Vec w;
2615     PetscCall(VecDuplicate(x, &w));
2616     PetscCall(VecCopy(x, w));
2617     PetscCall(VecConjugate(w));
2618     PetscCall(MatMultTranspose(mat, w, y));
2619     PetscCall(VecDestroy(&w));
2620     PetscCall(VecConjugate(y));
2621   }
2622   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2623 #else
2624   PetscCall(MatMultTranspose(mat, x, y));
2625 #endif
2626   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2627   PetscFunctionReturn(0);
2628 }
2629 
2630 /*@
2631     MatMultAdd -  Computes v3 = v2 + A * v1.
2632 
2633     Neighbor-wise Collective on mat
2634 
2635     Input Parameters:
2636 +   mat - the matrix
2637 -   v1, v2 - the vectors
2638 
2639     Output Parameters:
2640 .   v3 - the result
2641 
2642     Note:
2643     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2644     call `MatMultAdd`(A,v1,v2,v1).
2645 
2646     Level: beginner
2647 
2648 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2649 @*/
2650 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) {
2651   PetscFunctionBegin;
2652   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2653   PetscValidType(mat, 1);
2654   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2655   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2656   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2657 
2658   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2659   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2660   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);
2661   /* 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);
2662      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); */
2663   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);
2664   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);
2665   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2666   MatCheckPreallocated(mat, 1);
2667 
2668   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2669   PetscCall(VecLockReadPush(v1));
2670   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2671   PetscCall(VecLockReadPop(v1));
2672   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2673   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2674   PetscFunctionReturn(0);
2675 }
2676 
2677 /*@
2678    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2679 
2680    Neighbor-wise Collective on mat
2681 
2682    Input Parameters:
2683 +  mat - the matrix
2684 -  v1, v2 - the vectors
2685 
2686    Output Parameters:
2687 .  v3 - the result
2688 
2689    Note:
2690    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2691    call `MatMultTransposeAdd`(A,v1,v2,v1).
2692 
2693    Level: beginner
2694 
2695 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2696 @*/
2697 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) {
2698   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2699 
2700   PetscFunctionBegin;
2701   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2702   PetscValidType(mat, 1);
2703   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2704   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2705   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2706 
2707   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2708   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2709   PetscCheck(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);
2710   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);
2711   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);
2712   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2713   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2714   MatCheckPreallocated(mat, 1);
2715 
2716   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2717   PetscCall(VecLockReadPush(v1));
2718   PetscCall((*op)(mat, v1, v2, v3));
2719   PetscCall(VecLockReadPop(v1));
2720   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2721   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2722   PetscFunctionReturn(0);
2723 }
2724 
2725 /*@
2726    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2727 
2728    Neighbor-wise Collective on mat
2729 
2730    Input Parameters:
2731 +  mat - the matrix
2732 -  v1, v2 - the vectors
2733 
2734    Output Parameters:
2735 .  v3 - the result
2736 
2737    Note:
2738    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2739    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2740 
2741    Level: beginner
2742 
2743 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2744 @*/
2745 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) {
2746   PetscFunctionBegin;
2747   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2748   PetscValidType(mat, 1);
2749   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2750   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2751   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2752 
2753   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2754   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2755   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2756   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);
2757   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);
2758   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);
2759   MatCheckPreallocated(mat, 1);
2760 
2761   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2762   PetscCall(VecLockReadPush(v1));
2763   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2764   else {
2765     Vec w, z;
2766     PetscCall(VecDuplicate(v1, &w));
2767     PetscCall(VecCopy(v1, w));
2768     PetscCall(VecConjugate(w));
2769     PetscCall(VecDuplicate(v3, &z));
2770     PetscCall(MatMultTranspose(mat, w, z));
2771     PetscCall(VecDestroy(&w));
2772     PetscCall(VecConjugate(z));
2773     if (v2 != v3) {
2774       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2775     } else {
2776       PetscCall(VecAXPY(v3, 1.0, z));
2777     }
2778     PetscCall(VecDestroy(&z));
2779   }
2780   PetscCall(VecLockReadPop(v1));
2781   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2782   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2783   PetscFunctionReturn(0);
2784 }
2785 
2786 /*@C
2787    MatGetFactorType - gets the type of factorization it is
2788 
2789    Not Collective
2790 
2791    Input Parameters:
2792 .  mat - the matrix
2793 
2794    Output Parameters:
2795 .  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`
2796 
2797    Level: intermediate
2798 
2799 .seealso: `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2800           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2801 @*/
2802 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) {
2803   PetscFunctionBegin;
2804   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2805   PetscValidType(mat, 1);
2806   PetscValidPointer(t, 2);
2807   *t = mat->factortype;
2808   PetscFunctionReturn(0);
2809 }
2810 
2811 /*@C
2812    MatSetFactorType - sets the type of factorization it is
2813 
2814    Logically Collective on mat
2815 
2816    Input Parameters:
2817 +  mat - the matrix
2818 -  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`
2819 
2820    Level: intermediate
2821 
2822 .seealso: `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2823           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2824 @*/
2825 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) {
2826   PetscFunctionBegin;
2827   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2828   PetscValidType(mat, 1);
2829   mat->factortype = t;
2830   PetscFunctionReturn(0);
2831 }
2832 
2833 /* ------------------------------------------------------------*/
2834 /*@C
2835    MatGetInfo - Returns information about matrix storage (number of
2836    nonzeros, memory, etc.).
2837 
2838    Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2839 
2840    Input Parameter:
2841 .  mat - the matrix
2842 
2843    Output Parameters:
2844 +  flag - flag indicating the type of parameters to be returned
2845    (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2846    MAT_GLOBAL_SUM - sum over all processors)
2847 -  info - matrix information context
2848 
2849    Notes:
2850    The `MatInfo` context contains a variety of matrix data, including
2851    number of nonzeros allocated and used, number of mallocs during
2852    matrix assembly, etc.  Additional information for factored matrices
2853    is provided (such as the fill ratio, number of mallocs during
2854    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2855    when using the runtime options
2856 $       -info -mat_view ::ascii_info
2857 
2858    Example for C/C++ Users:
2859    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2860    data within the MatInfo context.  For example,
2861 .vb
2862       MatInfo info;
2863       Mat     A;
2864       double  mal, nz_a, nz_u;
2865 
2866       MatGetInfo(A,MAT_LOCAL,&info);
2867       mal  = info.mallocs;
2868       nz_a = info.nz_allocated;
2869 .ve
2870 
2871    Example for Fortran Users:
2872    Fortran users should declare info as a double precision
2873    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2874    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2875    a complete list of parameter names.
2876 .vb
2877       double  precision info(MAT_INFO_SIZE)
2878       double  precision mal, nz_a
2879       Mat     A
2880       integer ierr
2881 
2882       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2883       mal = info(MAT_INFO_MALLOCS)
2884       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2885 .ve
2886 
2887     Level: intermediate
2888 
2889     Developer Note: fortran interface is not autogenerated as the f90
2890     interface definition cannot be generated correctly [due to MatInfo]
2891 
2892 .seealso: `MatInfo`, `MatStashGetInfo()`
2893 @*/
2894 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) {
2895   PetscFunctionBegin;
2896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2897   PetscValidType(mat, 1);
2898   PetscValidPointer(info, 3);
2899   MatCheckPreallocated(mat, 1);
2900   PetscUseTypeMethod(mat, getinfo, flag, info);
2901   PetscFunctionReturn(0);
2902 }
2903 
2904 /*
2905    This is used by external packages where it is not easy to get the info from the actual
2906    matrix factorization.
2907 */
2908 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) {
2909   PetscFunctionBegin;
2910   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2911   PetscFunctionReturn(0);
2912 }
2913 
2914 /* ----------------------------------------------------------*/
2915 
2916 /*@C
2917    MatLUFactor - Performs in-place LU factorization of matrix.
2918 
2919    Collective on mat
2920 
2921    Input Parameters:
2922 +  mat - the matrix
2923 .  row - row permutation
2924 .  col - column permutation
2925 -  info - options for factorization, includes
2926 $          fill - expected fill as ratio of original fill.
2927 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2928 $                   Run with the option -info to determine an optimal value to use
2929 
2930    Notes:
2931    Most users should employ the `KSP` interface for linear solvers
2932    instead of working directly with matrix algebra routines such as this.
2933    See, e.g., `KSPCreate()`.
2934 
2935    This changes the state of the matrix to a factored matrix; it cannot be used
2936    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
2937 
2938    This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
2939    when not using `KSP`.
2940 
2941    Level: developer
2942 
2943    Developer Note:
2944    The Fortran interface is not autogenerated as the f90
2945    interface definition cannot be generated correctly [due to `MatFactorInfo`]
2946 
2947 .seealso: `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2948           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2949 @*/
2950 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) {
2951   MatFactorInfo tinfo;
2952 
2953   PetscFunctionBegin;
2954   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2955   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
2956   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
2957   if (info) PetscValidPointer(info, 4);
2958   PetscValidType(mat, 1);
2959   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2960   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2961   MatCheckPreallocated(mat, 1);
2962   if (!info) {
2963     PetscCall(MatFactorInfoInitialize(&tinfo));
2964     info = &tinfo;
2965   }
2966 
2967   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
2968   PetscUseTypeMethod(mat, lufactor, row, col, info);
2969   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
2970   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
2971   PetscFunctionReturn(0);
2972 }
2973 
2974 /*@C
2975    MatILUFactor - Performs in-place ILU factorization of matrix.
2976 
2977    Collective on mat
2978 
2979    Input Parameters:
2980 +  mat - the matrix
2981 .  row - row permutation
2982 .  col - column permutation
2983 -  info - structure containing
2984 $      levels - number of levels of fill.
2985 $      expected fill - as ratio of original fill.
2986 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
2987                 missing diagonal entries)
2988 
2989    Notes:
2990    Most users should employ the `KSP` interface for linear solvers
2991    instead of working directly with matrix algebra routines such as this.
2992    See, e.g., `KSPCreate()`.
2993 
2994    Probably really in-place only when level of fill is zero, otherwise allocates
2995    new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
2996    when not using `KSP`.
2997 
2998    Level: developer
2999 
3000    Developer Note:
3001    The Fortran interface is not autogenerated as the f90
3002    interface definition cannot be generated correctly [due to MatFactorInfo]
3003 
3004 .seealso: `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3005 @*/
3006 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) {
3007   PetscFunctionBegin;
3008   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3009   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3010   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3011   PetscValidPointer(info, 4);
3012   PetscValidType(mat, 1);
3013   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3014   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3015   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3016   MatCheckPreallocated(mat, 1);
3017 
3018   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3019   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3020   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3021   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3022   PetscFunctionReturn(0);
3023 }
3024 
3025 /*@C
3026    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3027    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3028 
3029    Collective on fact
3030 
3031    Input Parameters:
3032 +  fact - the factor matrix obtained with `MatGetFactor()`
3033 .  mat - the matrix
3034 .  row, col - row and column permutations
3035 -  info - options for factorization, includes
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 
3040    Notes:
3041     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
3042 
3043    Most users should employ the simplified `KSP` interface for linear solvers
3044    instead of working directly with matrix algebra routines such as this.
3045    See, e.g., `KSPCreate()`.
3046 
3047    Level: developer
3048 
3049    Developer Note:
3050    The Fortran interface is not autogenerated as the f90
3051    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3052 
3053 .seealso: `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3054 @*/
3055 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) {
3056   MatFactorInfo tinfo;
3057 
3058   PetscFunctionBegin;
3059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3060   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3061   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3062   if (info) PetscValidPointer(info, 5);
3063   PetscValidType(mat, 2);
3064   PetscValidPointer(fact, 1);
3065   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3066   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3067   if (!(fact)->ops->lufactorsymbolic) {
3068     MatSolverType stype;
3069     PetscCall(MatFactorGetSolverType(fact, &stype));
3070     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3071   }
3072   MatCheckPreallocated(mat, 2);
3073   if (!info) {
3074     PetscCall(MatFactorInfoInitialize(&tinfo));
3075     info = &tinfo;
3076   }
3077 
3078   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3079   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3080   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3081   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3082   PetscFunctionReturn(0);
3083 }
3084 
3085 /*@C
3086    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3087    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3088 
3089    Collective on fact
3090 
3091    Input Parameters:
3092 +  fact - the factor matrix obtained with `MatGetFactor()`
3093 .  mat - the matrix
3094 -  info - options for factorization
3095 
3096    Notes:
3097    See `MatLUFactor()` for in-place factorization.  See
3098    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3099 
3100    Most users should employ the `KSP` interface for linear solvers
3101    instead of working directly with matrix algebra routines such as this.
3102    See, e.g., `KSPCreate()`.
3103 
3104    Level: developer
3105 
3106     Developer Note:
3107     The Fortran interface is not autogenerated as the f90
3108     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3109 
3110 .seealso: `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3111 @*/
3112 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) {
3113   MatFactorInfo tinfo;
3114 
3115   PetscFunctionBegin;
3116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3117   PetscValidType(mat, 2);
3118   PetscValidPointer(fact, 1);
3119   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3120   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3121   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,
3122              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3123 
3124   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3125   MatCheckPreallocated(mat, 2);
3126   if (!info) {
3127     PetscCall(MatFactorInfoInitialize(&tinfo));
3128     info = &tinfo;
3129   }
3130 
3131   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3132   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3133   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3134   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3135   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3136   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3137   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3138   PetscFunctionReturn(0);
3139 }
3140 
3141 /*@C
3142    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3143    symmetric matrix.
3144 
3145    Collective on mat
3146 
3147    Input Parameters:
3148 +  mat - the matrix
3149 .  perm - row and column permutations
3150 -  f - expected fill as ratio of original fill
3151 
3152    Notes:
3153    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3154    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3155 
3156    Most users should employ the `KSP` interface for linear solvers
3157    instead of working directly with matrix algebra routines such as this.
3158    See, e.g., `KSPCreate()`.
3159 
3160    Level: developer
3161 
3162    Developer Note:
3163    The Fortran interface is not autogenerated as the f90
3164    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3165 
3166 .seealso: `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3167           `MatGetOrdering()`
3168 @*/
3169 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) {
3170   MatFactorInfo tinfo;
3171 
3172   PetscFunctionBegin;
3173   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3174   PetscValidType(mat, 1);
3175   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3176   if (info) PetscValidPointer(info, 3);
3177   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3178   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3179   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3180   MatCheckPreallocated(mat, 1);
3181   if (!info) {
3182     PetscCall(MatFactorInfoInitialize(&tinfo));
3183     info = &tinfo;
3184   }
3185 
3186   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3187   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3188   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3189   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3190   PetscFunctionReturn(0);
3191 }
3192 
3193 /*@C
3194    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3195    of a symmetric matrix.
3196 
3197    Collective on fact
3198 
3199    Input Parameters:
3200 +  fact - the factor matrix obtained with `MatGetFactor()`
3201 .  mat - the matrix
3202 .  perm - row and column permutations
3203 -  info - options for factorization, includes
3204 $          fill - expected fill as ratio of original fill.
3205 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3206 $                   Run with the option -info to determine an optimal value to use
3207 
3208    Notes:
3209    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3210    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3211 
3212    Most users should employ the `KSP` interface for linear solvers
3213    instead of working directly with matrix algebra routines such as this.
3214    See, e.g., `KSPCreate()`.
3215 
3216    Level: developer
3217 
3218    Developer Note:
3219    The Fortran interface is not autogenerated as the f90
3220    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3221 
3222 .seealso: `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3223           `MatGetOrdering()`
3224 @*/
3225 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) {
3226   MatFactorInfo tinfo;
3227 
3228   PetscFunctionBegin;
3229   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3230   PetscValidType(mat, 2);
3231   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3232   if (info) PetscValidPointer(info, 4);
3233   PetscValidPointer(fact, 1);
3234   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3235   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3236   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3237   if (!(fact)->ops->choleskyfactorsymbolic) {
3238     MatSolverType stype;
3239     PetscCall(MatFactorGetSolverType(fact, &stype));
3240     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3241   }
3242   MatCheckPreallocated(mat, 2);
3243   if (!info) {
3244     PetscCall(MatFactorInfoInitialize(&tinfo));
3245     info = &tinfo;
3246   }
3247 
3248   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3249   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3250   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3251   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3252   PetscFunctionReturn(0);
3253 }
3254 
3255 /*@C
3256    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3257    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3258    `MatCholeskyFactorSymbolic()`.
3259 
3260    Collective on fact
3261 
3262    Input Parameters:
3263 +  fact - the factor matrix obtained with `MatGetFactor()`
3264 .  mat - the initial matrix
3265 .  info - options for factorization
3266 -  fact - the symbolic factor of mat
3267 
3268    Note:
3269    Most users should employ the `KSP` interface for linear solvers
3270    instead of working directly with matrix algebra routines such as this.
3271    See, e.g., `KSPCreate()`.
3272 
3273    Level: developer
3274 
3275    Developer Note:
3276    The Fortran interface is not autogenerated as the f90
3277    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3278 
3279 .seealso: `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3280 @*/
3281 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) {
3282   MatFactorInfo tinfo;
3283 
3284   PetscFunctionBegin;
3285   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3286   PetscValidType(mat, 2);
3287   PetscValidPointer(fact, 1);
3288   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3289   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3290   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3291   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,
3292              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3293   MatCheckPreallocated(mat, 2);
3294   if (!info) {
3295     PetscCall(MatFactorInfoInitialize(&tinfo));
3296     info = &tinfo;
3297   }
3298 
3299   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3300   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3301   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3302   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3303   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3304   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3305   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3306   PetscFunctionReturn(0);
3307 }
3308 
3309 /*@
3310    MatQRFactor - Performs in-place QR factorization of matrix.
3311 
3312    Collective on mat
3313 
3314    Input Parameters:
3315 +  mat - the matrix
3316 .  col - column permutation
3317 -  info - options for factorization, includes
3318 $          fill - expected fill as ratio of original fill.
3319 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3320 $                   Run with the option -info to determine an optimal value to use
3321 
3322    Notes:
3323    Most users should employ the `KSP` interface for linear solvers
3324    instead of working directly with matrix algebra routines such as this.
3325    See, e.g., `KSPCreate()`.
3326 
3327    This changes the state of the matrix to a factored matrix; it cannot be used
3328    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3329 
3330    Level: developer
3331 
3332    Developer Note:
3333    The Fortran interface is not autogenerated as the f90
3334    interface definition cannot be generated correctly [due to MatFactorInfo]
3335 
3336 .seealso: `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3337           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3338 @*/
3339 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) {
3340   PetscFunctionBegin;
3341   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3342   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3343   if (info) PetscValidPointer(info, 3);
3344   PetscValidType(mat, 1);
3345   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3346   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3347   MatCheckPreallocated(mat, 1);
3348   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3349   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3350   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3351   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3352   PetscFunctionReturn(0);
3353 }
3354 
3355 /*@
3356    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3357    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3358 
3359    Collective on fact
3360 
3361    Input Parameters:
3362 +  fact - the factor matrix obtained with `MatGetFactor()`
3363 .  mat - the matrix
3364 .  col - column permutation
3365 -  info - options for factorization, includes
3366 $          fill - expected fill as ratio of original fill.
3367 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3368 $                   Run with the option -info to determine an optimal value to use
3369 
3370    Most users should employ the `KSP` interface for linear solvers
3371    instead of working directly with matrix algebra routines such as this.
3372    See, e.g., `KSPCreate()`.
3373 
3374    Level: developer
3375 
3376    Developer Note:
3377    The Fortran interface is not autogenerated as the f90
3378    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3379 
3380 .seealso: `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3381 @*/
3382 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) {
3383   MatFactorInfo tinfo;
3384 
3385   PetscFunctionBegin;
3386   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3387   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3388   if (info) PetscValidPointer(info, 4);
3389   PetscValidType(mat, 2);
3390   PetscValidPointer(fact, 1);
3391   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3392   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3393   MatCheckPreallocated(mat, 2);
3394   if (!info) {
3395     PetscCall(MatFactorInfoInitialize(&tinfo));
3396     info = &tinfo;
3397   }
3398 
3399   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3400   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3401   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3402   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3403   PetscFunctionReturn(0);
3404 }
3405 
3406 /*@
3407    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3408    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3409 
3410    Collective on fact
3411 
3412    Input Parameters:
3413 +  fact - the factor matrix obtained with `MatGetFactor()`
3414 .  mat - the matrix
3415 -  info - options for factorization
3416 
3417    Notes:
3418    See `MatQRFactor()` for in-place factorization.
3419 
3420    Most users should employ the `KSP` interface for linear solvers
3421    instead of working directly with matrix algebra routines such as this.
3422    See, e.g., `KSPCreate()`.
3423 
3424    Level: developer
3425 
3426    Developer Note:
3427    The Fortran interface is not autogenerated as the f90
3428    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3429 
3430 .seealso: `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3431 @*/
3432 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) {
3433   MatFactorInfo tinfo;
3434 
3435   PetscFunctionBegin;
3436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3437   PetscValidType(mat, 2);
3438   PetscValidPointer(fact, 1);
3439   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3440   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3441   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,
3442              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3443 
3444   MatCheckPreallocated(mat, 2);
3445   if (!info) {
3446     PetscCall(MatFactorInfoInitialize(&tinfo));
3447     info = &tinfo;
3448   }
3449 
3450   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3451   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3452   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3453   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3454   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3455   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3456   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3457   PetscFunctionReturn(0);
3458 }
3459 
3460 /* ----------------------------------------------------------------*/
3461 /*@
3462    MatSolve - Solves A x = b, given a factored matrix.
3463 
3464    Neighbor-wise Collective on mat
3465 
3466    Input Parameters:
3467 +  mat - the factored matrix
3468 -  b - the right-hand-side vector
3469 
3470    Output Parameter:
3471 .  x - the result vector
3472 
3473    Notes:
3474    The vectors b and x cannot be the same.  I.e., one cannot
3475    call `MatSolve`(A,x,x).
3476 
3477    Most users should employ the `KSP` interface for linear solvers
3478    instead of working directly with matrix algebra routines such as this.
3479    See, e.g., `KSPCreate()`.
3480 
3481    Level: developer
3482 
3483 .seealso: `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3484 @*/
3485 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) {
3486   PetscFunctionBegin;
3487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3488   PetscValidType(mat, 1);
3489   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3490   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3491   PetscCheckSameComm(mat, 1, b, 2);
3492   PetscCheckSameComm(mat, 1, x, 3);
3493   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3494   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);
3495   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);
3496   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);
3497   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3498   MatCheckPreallocated(mat, 1);
3499 
3500   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3501   if (mat->factorerrortype) {
3502     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3503     PetscCall(VecSetInf(x));
3504   } else PetscUseTypeMethod(mat, solve, b, x);
3505   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3506   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3507   PetscFunctionReturn(0);
3508 }
3509 
3510 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) {
3511   Vec      b, x;
3512   PetscInt N, i;
3513   PetscErrorCode (*f)(Mat, Vec, Vec);
3514   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3515 
3516   PetscFunctionBegin;
3517   if (A->factorerrortype) {
3518     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3519     PetscCall(MatSetInf(X));
3520     PetscFunctionReturn(0);
3521   }
3522   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3523   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3524   PetscCall(MatBoundToCPU(A, &Abound));
3525   if (!Abound) {
3526     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3527     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3528   }
3529   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3530   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3531   PetscCall(MatGetSize(B, NULL, &N));
3532   for (i = 0; i < N; i++) {
3533     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3534     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3535     PetscCall((*f)(A, b, x));
3536     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3537     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3538   }
3539   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3540   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3541   PetscFunctionReturn(0);
3542 }
3543 
3544 /*@
3545    MatMatSolve - Solves A X = B, given a factored matrix.
3546 
3547    Neighbor-wise Collective on A
3548 
3549    Input Parameters:
3550 +  A - the factored matrix
3551 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3552 
3553    Output Parameter:
3554 .  X - the result matrix (dense matrix)
3555 
3556    Note:
3557    If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3558    otherwise, B and X cannot be the same.
3559 
3560    Level: developer
3561 
3562 .seealso: `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3563 @*/
3564 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) {
3565   PetscFunctionBegin;
3566   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3567   PetscValidType(A, 1);
3568   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3569   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3570   PetscCheckSameComm(A, 1, B, 2);
3571   PetscCheckSameComm(A, 1, X, 3);
3572   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);
3573   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);
3574   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");
3575   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3576   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3577   MatCheckPreallocated(A, 1);
3578 
3579   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3580   if (!A->ops->matsolve) {
3581     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3582     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3583   } else PetscUseTypeMethod(A, matsolve, B, X);
3584   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3585   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3586   PetscFunctionReturn(0);
3587 }
3588 
3589 /*@
3590    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3591 
3592    Neighbor-wise Collective on A
3593 
3594    Input Parameters:
3595 +  A - the factored matrix
3596 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3597 
3598    Output Parameter:
3599 .  X - the result matrix (dense matrix)
3600 
3601    Note:
3602    The matrices B and X cannot be the same.  I.e., one cannot
3603    call `MatMatSolveTranspose`(A,X,X).
3604 
3605    Level: developer
3606 
3607 .seealso: `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3608 @*/
3609 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) {
3610   PetscFunctionBegin;
3611   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3612   PetscValidType(A, 1);
3613   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3614   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3615   PetscCheckSameComm(A, 1, B, 2);
3616   PetscCheckSameComm(A, 1, X, 3);
3617   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3618   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);
3619   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);
3620   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);
3621   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");
3622   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3623   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3624   MatCheckPreallocated(A, 1);
3625 
3626   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3627   if (!A->ops->matsolvetranspose) {
3628     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3629     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3630   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3631   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3632   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3633   PetscFunctionReturn(0);
3634 }
3635 
3636 /*@
3637    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3638 
3639    Neighbor-wise Collective on A
3640 
3641    Input Parameters:
3642 +  A - the factored matrix
3643 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3644 
3645    Output Parameter:
3646 .  X - the result matrix (dense matrix)
3647 
3648    Note:
3649    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
3650    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3651 
3652    Level: developer
3653 
3654 .seealso: `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3655 @*/
3656 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) {
3657   PetscFunctionBegin;
3658   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3659   PetscValidType(A, 1);
3660   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3661   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3662   PetscCheckSameComm(A, 1, Bt, 2);
3663   PetscCheckSameComm(A, 1, X, 3);
3664 
3665   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3666   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);
3667   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);
3668   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");
3669   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3670   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3671   MatCheckPreallocated(A, 1);
3672 
3673   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3674   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3675   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3676   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3677   PetscFunctionReturn(0);
3678 }
3679 
3680 /*@
3681    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3682                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3683 
3684    Neighbor-wise Collective on mat
3685 
3686    Input Parameters:
3687 +  mat - the factored matrix
3688 -  b - the right-hand-side vector
3689 
3690    Output Parameter:
3691 .  x - the result vector
3692 
3693    Notes:
3694    `MatSolve()` should be used for most applications, as it performs
3695    a forward solve followed by a backward solve.
3696 
3697    The vectors b and x cannot be the same,  i.e., one cannot
3698    call `MatForwardSolve`(A,x,x).
3699 
3700    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3701    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3702    `MatForwardSolve()` solves U^T*D y = b, and
3703    `MatBackwardSolve()` solves U x = y.
3704    Thus they do not provide a symmetric preconditioner.
3705 
3706    Level: developer
3707 
3708 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3709 @*/
3710 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) {
3711   PetscFunctionBegin;
3712   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3713   PetscValidType(mat, 1);
3714   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3715   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3716   PetscCheckSameComm(mat, 1, b, 2);
3717   PetscCheckSameComm(mat, 1, x, 3);
3718   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3719   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);
3720   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);
3721   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);
3722   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3723   MatCheckPreallocated(mat, 1);
3724 
3725   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3726   PetscUseTypeMethod(mat, forwardsolve, b, x);
3727   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3728   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3729   PetscFunctionReturn(0);
3730 }
3731 
3732 /*@
3733    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3734                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3735 
3736    Neighbor-wise Collective on mat
3737 
3738    Input Parameters:
3739 +  mat - the factored matrix
3740 -  b - the right-hand-side vector
3741 
3742    Output Parameter:
3743 .  x - the result vector
3744 
3745    Notes:
3746    `MatSolve()` should be used for most applications, as it performs
3747    a forward solve followed by a backward solve.
3748 
3749    The vectors b and x cannot be the same.  I.e., one cannot
3750    call `MatBackwardSolve`(A,x,x).
3751 
3752    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3753    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3754    `MatForwardSolve()` solves U^T*D y = b, and
3755    `MatBackwardSolve()` solves U x = y.
3756    Thus they do not provide a symmetric preconditioner.
3757 
3758    Level: developer
3759 
3760 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3761 @*/
3762 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) {
3763   PetscFunctionBegin;
3764   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3765   PetscValidType(mat, 1);
3766   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3767   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3768   PetscCheckSameComm(mat, 1, b, 2);
3769   PetscCheckSameComm(mat, 1, x, 3);
3770   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3771   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);
3772   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);
3773   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);
3774   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3775   MatCheckPreallocated(mat, 1);
3776 
3777   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3778   PetscUseTypeMethod(mat, backwardsolve, b, x);
3779   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3780   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3781   PetscFunctionReturn(0);
3782 }
3783 
3784 /*@
3785    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3786 
3787    Neighbor-wise Collective on mat
3788 
3789    Input Parameters:
3790 +  mat - the factored matrix
3791 .  b - the right-hand-side vector
3792 -  y - the vector to be added to
3793 
3794    Output Parameter:
3795 .  x - the result vector
3796 
3797    Note:
3798    The vectors b and x cannot be the same.  I.e., one cannot
3799    call `MatSolveAdd`(A,x,y,x).
3800 
3801    Level: developer
3802 
3803 .seealso: `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3804 @*/
3805 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) {
3806   PetscScalar one = 1.0;
3807   Vec         tmp;
3808 
3809   PetscFunctionBegin;
3810   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3811   PetscValidType(mat, 1);
3812   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3813   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3814   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3815   PetscCheckSameComm(mat, 1, b, 2);
3816   PetscCheckSameComm(mat, 1, y, 3);
3817   PetscCheckSameComm(mat, 1, x, 4);
3818   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3819   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);
3820   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);
3821   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);
3822   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);
3823   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);
3824   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3825   MatCheckPreallocated(mat, 1);
3826 
3827   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3828   if (mat->factorerrortype) {
3829     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3830     PetscCall(VecSetInf(x));
3831   } else if (mat->ops->solveadd) {
3832     PetscUseTypeMethod(mat, solveadd, b, y, x);
3833   } else {
3834     /* do the solve then the add manually */
3835     if (x != y) {
3836       PetscCall(MatSolve(mat, b, x));
3837       PetscCall(VecAXPY(x, one, y));
3838     } else {
3839       PetscCall(VecDuplicate(x, &tmp));
3840       PetscCall(PetscLogObjectParent((PetscObject)mat, (PetscObject)tmp));
3841       PetscCall(VecCopy(x, tmp));
3842       PetscCall(MatSolve(mat, b, x));
3843       PetscCall(VecAXPY(x, one, tmp));
3844       PetscCall(VecDestroy(&tmp));
3845     }
3846   }
3847   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3848   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3849   PetscFunctionReturn(0);
3850 }
3851 
3852 /*@
3853    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3854 
3855    Neighbor-wise Collective on mat
3856 
3857    Input Parameters:
3858 +  mat - the factored matrix
3859 -  b - the right-hand-side vector
3860 
3861    Output Parameter:
3862 .  x - the result vector
3863 
3864    Notes:
3865    The vectors b and x cannot be the same.  I.e., one cannot
3866    call `MatSolveTranspose`(A,x,x).
3867 
3868    Most users should employ the `KSP` interface for linear solvers
3869    instead of working directly with matrix algebra routines such as this.
3870    See, e.g., `KSPCreate()`.
3871 
3872    Level: developer
3873 
3874 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3875 @*/
3876 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) {
3877   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3878 
3879   PetscFunctionBegin;
3880   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3881   PetscValidType(mat, 1);
3882   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3883   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3884   PetscCheckSameComm(mat, 1, b, 2);
3885   PetscCheckSameComm(mat, 1, x, 3);
3886   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3887   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);
3888   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);
3889   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3890   MatCheckPreallocated(mat, 1);
3891   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3892   if (mat->factorerrortype) {
3893     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3894     PetscCall(VecSetInf(x));
3895   } else {
3896     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
3897     PetscCall((*f)(mat, b, x));
3898   }
3899   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
3900   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3901   PetscFunctionReturn(0);
3902 }
3903 
3904 /*@
3905    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3906                       factored matrix.
3907 
3908    Neighbor-wise Collective on mat
3909 
3910    Input Parameters:
3911 +  mat - the factored matrix
3912 .  b - the right-hand-side vector
3913 -  y - the vector to be added to
3914 
3915    Output Parameter:
3916 .  x - the result vector
3917 
3918    Note:
3919    The vectors b and x cannot be the same.  I.e., one cannot
3920    call `MatSolveTransposeAdd`(A,x,y,x).
3921 
3922    Level: developer
3923 
3924 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3925 @*/
3926 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) {
3927   PetscScalar one = 1.0;
3928   Vec         tmp;
3929   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
3930 
3931   PetscFunctionBegin;
3932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3933   PetscValidType(mat, 1);
3934   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3935   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3936   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3937   PetscCheckSameComm(mat, 1, b, 2);
3938   PetscCheckSameComm(mat, 1, y, 3);
3939   PetscCheckSameComm(mat, 1, x, 4);
3940   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3941   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);
3942   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);
3943   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);
3944   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);
3945   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3946   MatCheckPreallocated(mat, 1);
3947 
3948   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
3949   if (mat->factorerrortype) {
3950     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3951     PetscCall(VecSetInf(x));
3952   } else if (f) {
3953     PetscCall((*f)(mat, b, y, x));
3954   } else {
3955     /* do the solve then the add manually */
3956     if (x != y) {
3957       PetscCall(MatSolveTranspose(mat, b, x));
3958       PetscCall(VecAXPY(x, one, y));
3959     } else {
3960       PetscCall(VecDuplicate(x, &tmp));
3961       PetscCall(PetscLogObjectParent((PetscObject)mat, (PetscObject)tmp));
3962       PetscCall(VecCopy(x, tmp));
3963       PetscCall(MatSolveTranspose(mat, b, x));
3964       PetscCall(VecAXPY(x, one, tmp));
3965       PetscCall(VecDestroy(&tmp));
3966     }
3967   }
3968   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
3969   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3970   PetscFunctionReturn(0);
3971 }
3972 /* ----------------------------------------------------------------*/
3973 
3974 /*@
3975    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
3976 
3977    Neighbor-wise Collective on mat
3978 
3979    Input Parameters:
3980 +  mat - the matrix
3981 .  b - the right hand side
3982 .  omega - the relaxation factor
3983 .  flag - flag indicating the type of SOR (see below)
3984 .  shift -  diagonal shift
3985 .  its - the number of iterations
3986 -  lits - the number of local iterations
3987 
3988    Output Parameter:
3989 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
3990 
3991    SOR Flags:
3992 +     `SOR_FORWARD_SWEEP` - forward SOR
3993 .     `SOR_BACKWARD_SWEEP` - backward SOR
3994 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
3995 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
3996 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
3997 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
3998 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
3999 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4000          upper/lower triangular part of matrix to
4001          vector (with omega)
4002 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4003 
4004    Notes:
4005    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4006    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4007    on each processor.
4008 
4009    Application programmers will not generally use `MatSOR()` directly,
4010    but instead will employ the `KSP`/`PC` interface.
4011 
4012    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4013 
4014    Most users should employ the `KSP` interface for linear solvers
4015    instead of working directly with matrix algebra routines such as this.
4016    See, e.g., `KSPCreate()`.
4017 
4018    Vectors x and b CANNOT be the same
4019 
4020    Notes for Advanced Users:
4021    The flags are implemented as bitwise inclusive or operations.
4022    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4023    to specify a zero initial guess for SSOR.
4024 
4025    Developer Note:
4026    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4027 
4028    Level: developer
4029 
4030 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4031 @*/
4032 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) {
4033   PetscFunctionBegin;
4034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4035   PetscValidType(mat, 1);
4036   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4037   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4038   PetscCheckSameComm(mat, 1, b, 2);
4039   PetscCheckSameComm(mat, 1, x, 8);
4040   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4041   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4042   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);
4043   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);
4044   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);
4045   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4046   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4047   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4048 
4049   MatCheckPreallocated(mat, 1);
4050   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4051   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4052   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4053   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4054   PetscFunctionReturn(0);
4055 }
4056 
4057 /*
4058       Default matrix copy routine.
4059 */
4060 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) {
4061   PetscInt           i, rstart = 0, rend = 0, nz;
4062   const PetscInt    *cwork;
4063   const PetscScalar *vwork;
4064 
4065   PetscFunctionBegin;
4066   if (B->assembled) PetscCall(MatZeroEntries(B));
4067   if (str == SAME_NONZERO_PATTERN) {
4068     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4069     for (i = rstart; i < rend; i++) {
4070       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4071       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4072       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4073     }
4074   } else {
4075     PetscCall(MatAYPX(B, 0.0, A, str));
4076   }
4077   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4078   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4079   PetscFunctionReturn(0);
4080 }
4081 
4082 /*@
4083    MatCopy - Copies a matrix to another matrix.
4084 
4085    Collective on A
4086 
4087    Input Parameters:
4088 +  A - the matrix
4089 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4090 
4091    Output Parameter:
4092 .  B - where the copy is put
4093 
4094    Notes:
4095    If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4096 
4097    `MatCopy()` copies the matrix entries of a matrix to another existing
4098    matrix (after first zeroing the second matrix).  A related routine is
4099    `MatConvert()`, which first creates a new matrix and then copies the data.
4100 
4101    Level: intermediate
4102 
4103 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4104 @*/
4105 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) {
4106   PetscInt i;
4107 
4108   PetscFunctionBegin;
4109   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4110   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4111   PetscValidType(A, 1);
4112   PetscValidType(B, 2);
4113   PetscCheckSameComm(A, 1, B, 2);
4114   MatCheckPreallocated(B, 2);
4115   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4116   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4117   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,
4118              A->cmap->N, B->cmap->N);
4119   MatCheckPreallocated(A, 1);
4120   if (A == B) PetscFunctionReturn(0);
4121 
4122   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4123   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4124   else PetscCall(MatCopy_Basic(A, B, str));
4125 
4126   B->stencil.dim = A->stencil.dim;
4127   B->stencil.noc = A->stencil.noc;
4128   for (i = 0; i <= A->stencil.dim; i++) {
4129     B->stencil.dims[i]   = A->stencil.dims[i];
4130     B->stencil.starts[i] = A->stencil.starts[i];
4131   }
4132 
4133   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4134   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4135   PetscFunctionReturn(0);
4136 }
4137 
4138 /*@C
4139    MatConvert - Converts a matrix to another matrix, either of the same
4140    or different type.
4141 
4142    Collective on mat
4143 
4144    Input Parameters:
4145 +  mat - the matrix
4146 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4147    same type as the original matrix.
4148 -  reuse - denotes if the destination matrix is to be created or reused.
4149    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
4150    `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).
4151 
4152    Output Parameter:
4153 .  M - pointer to place new matrix
4154 
4155    Notes:
4156    `MatConvert()` first creates a new matrix and then copies the data from
4157    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4158    entries of one matrix to another already existing matrix context.
4159 
4160    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4161    the MPI communicator of the generated matrix is always the same as the communicator
4162    of the input matrix.
4163 
4164    Level: intermediate
4165 
4166 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4167 @*/
4168 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) {
4169   PetscBool  sametype, issame, flg;
4170   PetscBool3 issymmetric, ishermitian;
4171   char       convname[256], mtype[256];
4172   Mat        B;
4173 
4174   PetscFunctionBegin;
4175   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4176   PetscValidType(mat, 1);
4177   PetscValidPointer(M, 4);
4178   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4179   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4180   MatCheckPreallocated(mat, 1);
4181 
4182   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4183   if (flg) newtype = mtype;
4184 
4185   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4186   PetscCall(PetscStrcmp(newtype, "same", &issame));
4187   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4188   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");
4189 
4190   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4191     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4192     PetscFunctionReturn(0);
4193   }
4194 
4195   /* Cache Mat options because some converters use MatHeaderReplace  */
4196   issymmetric = mat->symmetric;
4197   ishermitian = mat->hermitian;
4198 
4199   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4200     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4201     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4202   } else {
4203     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4204     const char *prefix[3]                                 = {"seq", "mpi", ""};
4205     PetscInt    i;
4206     /*
4207        Order of precedence:
4208        0) See if newtype is a superclass of the current matrix.
4209        1) See if a specialized converter is known to the current matrix.
4210        2) See if a specialized converter is known to the desired matrix class.
4211        3) See if a good general converter is registered for the desired class
4212           (as of 6/27/03 only MATMPIADJ falls into this category).
4213        4) See if a good general converter is known for the current matrix.
4214        5) Use a really basic converter.
4215     */
4216 
4217     /* 0) See if newtype is a superclass of the current matrix.
4218           i.e mat is mpiaij and newtype is aij */
4219     for (i = 0; i < 2; i++) {
4220       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4221       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4222       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4223       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4224       if (flg) {
4225         if (reuse == MAT_INPLACE_MATRIX) {
4226           PetscCall(PetscInfo(mat, "Early return\n"));
4227           PetscFunctionReturn(0);
4228         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4229           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4230           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4231           PetscFunctionReturn(0);
4232         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4233           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4234           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4235           PetscFunctionReturn(0);
4236         }
4237       }
4238     }
4239     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4240     for (i = 0; i < 3; i++) {
4241       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4242       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4243       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4244       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4245       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4246       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4247       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4248       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4249       if (conv) goto foundconv;
4250     }
4251 
4252     /* 2)  See if a specialized converter is known to the desired matrix class. */
4253     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4254     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4255     PetscCall(MatSetType(B, newtype));
4256     for (i = 0; i < 3; i++) {
4257       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4258       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4259       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4260       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4261       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4262       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4263       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4264       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4265       if (conv) {
4266         PetscCall(MatDestroy(&B));
4267         goto foundconv;
4268       }
4269     }
4270 
4271     /* 3) See if a good general converter is registered for the desired class */
4272     conv = B->ops->convertfrom;
4273     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4274     PetscCall(MatDestroy(&B));
4275     if (conv) goto foundconv;
4276 
4277     /* 4) See if a good general converter is known for the current matrix */
4278     if (mat->ops->convert) conv = mat->ops->convert;
4279     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4280     if (conv) goto foundconv;
4281 
4282     /* 5) Use a really basic converter. */
4283     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4284     conv = MatConvert_Basic;
4285 
4286   foundconv:
4287     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4288     PetscCall((*conv)(mat, newtype, reuse, M));
4289     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4290       /* the block sizes must be same if the mappings are copied over */
4291       (*M)->rmap->bs = mat->rmap->bs;
4292       (*M)->cmap->bs = mat->cmap->bs;
4293       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4294       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4295       (*M)->rmap->mapping = mat->rmap->mapping;
4296       (*M)->cmap->mapping = mat->cmap->mapping;
4297     }
4298     (*M)->stencil.dim = mat->stencil.dim;
4299     (*M)->stencil.noc = mat->stencil.noc;
4300     for (i = 0; i <= mat->stencil.dim; i++) {
4301       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4302       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4303     }
4304     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4305   }
4306   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4307 
4308   /* Copy Mat options */
4309   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4310   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4311   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4312   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4313   PetscFunctionReturn(0);
4314 }
4315 
4316 /*@C
4317    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4318 
4319    Not Collective
4320 
4321    Input Parameter:
4322 .  mat - the matrix, must be a factored matrix
4323 
4324    Output Parameter:
4325 .   type - the string name of the package (do not free this string)
4326 
4327    Note:
4328       In Fortran you pass in a empty string and the package name will be copied into it.
4329     (Make sure the string is long enough)
4330 
4331    Level: intermediate
4332 
4333 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4334 @*/
4335 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) {
4336   PetscErrorCode (*conv)(Mat, MatSolverType *);
4337 
4338   PetscFunctionBegin;
4339   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4340   PetscValidType(mat, 1);
4341   PetscValidPointer(type, 2);
4342   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4343   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4344   if (conv) PetscCall((*conv)(mat, type));
4345   else *type = MATSOLVERPETSC;
4346   PetscFunctionReturn(0);
4347 }
4348 
4349 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4350 struct _MatSolverTypeForSpecifcType {
4351   MatType mtype;
4352   /* no entry for MAT_FACTOR_NONE */
4353   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4354   MatSolverTypeForSpecifcType next;
4355 };
4356 
4357 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4358 struct _MatSolverTypeHolder {
4359   char                       *name;
4360   MatSolverTypeForSpecifcType handlers;
4361   MatSolverTypeHolder         next;
4362 };
4363 
4364 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4365 
4366 /*@C
4367    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4368 
4369    Input Parameters:
4370 +    package - name of the package, for example petsc or superlu
4371 .    mtype - the matrix type that works with this package
4372 .    ftype - the type of factorization supported by the package
4373 -    createfactor - routine that will create the factored matrix ready to be used
4374 
4375     Level: developer
4376 
4377 .seealso: `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4378 @*/
4379 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) {
4380   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4381   PetscBool                   flg;
4382   MatSolverTypeForSpecifcType inext, iprev = NULL;
4383 
4384   PetscFunctionBegin;
4385   PetscCall(MatInitializePackage());
4386   if (!next) {
4387     PetscCall(PetscNew(&MatSolverTypeHolders));
4388     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4389     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4390     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4391     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4392     PetscFunctionReturn(0);
4393   }
4394   while (next) {
4395     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4396     if (flg) {
4397       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4398       inext = next->handlers;
4399       while (inext) {
4400         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4401         if (flg) {
4402           inext->createfactor[(int)ftype - 1] = createfactor;
4403           PetscFunctionReturn(0);
4404         }
4405         iprev = inext;
4406         inext = inext->next;
4407       }
4408       PetscCall(PetscNew(&iprev->next));
4409       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4410       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4411       PetscFunctionReturn(0);
4412     }
4413     prev = next;
4414     next = next->next;
4415   }
4416   PetscCall(PetscNew(&prev->next));
4417   PetscCall(PetscStrallocpy(package, &prev->next->name));
4418   PetscCall(PetscNew(&prev->next->handlers));
4419   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4420   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4421   PetscFunctionReturn(0);
4422 }
4423 
4424 /*@C
4425    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4426 
4427    Input Parameters:
4428 +    type - name of the package, for example petsc or superlu
4429 .    ftype - the type of factorization supported by the type
4430 -    mtype - the matrix type that works with this type
4431 
4432    Output Parameters:
4433 +   foundtype - `PETSC_TRUE` if the type was registered
4434 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4435 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4436 
4437     Level: developer
4438 
4439 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4440 @*/
4441 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) {
4442   MatSolverTypeHolder         next = MatSolverTypeHolders;
4443   PetscBool                   flg;
4444   MatSolverTypeForSpecifcType inext;
4445 
4446   PetscFunctionBegin;
4447   if (foundtype) *foundtype = PETSC_FALSE;
4448   if (foundmtype) *foundmtype = PETSC_FALSE;
4449   if (createfactor) *createfactor = NULL;
4450 
4451   if (type) {
4452     while (next) {
4453       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4454       if (flg) {
4455         if (foundtype) *foundtype = PETSC_TRUE;
4456         inext = next->handlers;
4457         while (inext) {
4458           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4459           if (flg) {
4460             if (foundmtype) *foundmtype = PETSC_TRUE;
4461             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4462             PetscFunctionReturn(0);
4463           }
4464           inext = inext->next;
4465         }
4466       }
4467       next = next->next;
4468     }
4469   } else {
4470     while (next) {
4471       inext = next->handlers;
4472       while (inext) {
4473         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4474         if (flg && inext->createfactor[(int)ftype - 1]) {
4475           if (foundtype) *foundtype = PETSC_TRUE;
4476           if (foundmtype) *foundmtype = PETSC_TRUE;
4477           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4478           PetscFunctionReturn(0);
4479         }
4480         inext = inext->next;
4481       }
4482       next = next->next;
4483     }
4484     /* try with base classes inext->mtype */
4485     next = MatSolverTypeHolders;
4486     while (next) {
4487       inext = next->handlers;
4488       while (inext) {
4489         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4490         if (flg && inext->createfactor[(int)ftype - 1]) {
4491           if (foundtype) *foundtype = PETSC_TRUE;
4492           if (foundmtype) *foundmtype = PETSC_TRUE;
4493           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4494           PetscFunctionReturn(0);
4495         }
4496         inext = inext->next;
4497       }
4498       next = next->next;
4499     }
4500   }
4501   PetscFunctionReturn(0);
4502 }
4503 
4504 PetscErrorCode MatSolverTypeDestroy(void) {
4505   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4506   MatSolverTypeForSpecifcType inext, iprev;
4507 
4508   PetscFunctionBegin;
4509   while (next) {
4510     PetscCall(PetscFree(next->name));
4511     inext = next->handlers;
4512     while (inext) {
4513       PetscCall(PetscFree(inext->mtype));
4514       iprev = inext;
4515       inext = inext->next;
4516       PetscCall(PetscFree(iprev));
4517     }
4518     prev = next;
4519     next = next->next;
4520     PetscCall(PetscFree(prev));
4521   }
4522   MatSolverTypeHolders = NULL;
4523   PetscFunctionReturn(0);
4524 }
4525 
4526 /*@C
4527    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4528 
4529    Logically Collective on mat
4530 
4531    Input Parameters:
4532 .  mat - the matrix
4533 
4534    Output Parameters:
4535 .  flg - `PETSC_TRUE` if uses the ordering
4536 
4537    Note:
4538    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4539    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4540 
4541    Level: developer
4542 
4543 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4544 @*/
4545 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) {
4546   PetscFunctionBegin;
4547   *flg = mat->canuseordering;
4548   PetscFunctionReturn(0);
4549 }
4550 
4551 /*@C
4552    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4553 
4554    Logically Collective on mat
4555 
4556    Input Parameters:
4557 .  mat - the matrix obtained with `MatGetFactor()`
4558 
4559    Output Parameters:
4560 .  otype - the preferred type
4561 
4562    Level: developer
4563 
4564 .seealso: `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4565 @*/
4566 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) {
4567   PetscFunctionBegin;
4568   *otype = mat->preferredordering[ftype];
4569   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4570   PetscFunctionReturn(0);
4571 }
4572 
4573 /*@C
4574    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4575 
4576    Collective on mat
4577 
4578    Input Parameters:
4579 +  mat - the matrix
4580 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4581 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4582 
4583    Output Parameters:
4584 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4585 
4586    Options Database Key:
4587 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4588                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4589 
4590    Notes:
4591      Users usually access the factorization solvers via `KSP`
4592 
4593       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4594      such as pastix, superlu, mumps etc.
4595 
4596       PETSc must have been ./configure to use the external solver, using the option --download-package
4597 
4598       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4599       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4600       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4601 
4602    Developer Note:
4603       This should actually be called `MatCreateFactor()` since it creates a new factor object
4604 
4605    Level: intermediate
4606 
4607 .seealso: `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4608           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4609 @*/
4610 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) {
4611   PetscBool foundtype, foundmtype;
4612   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4613 
4614   PetscFunctionBegin;
4615   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4616   PetscValidType(mat, 1);
4617 
4618   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4619   MatCheckPreallocated(mat, 1);
4620 
4621   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4622   if (!foundtype) {
4623     if (type) {
4624       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],
4625               ((PetscObject)mat)->type_name, type);
4626     } else {
4627       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);
4628     }
4629   }
4630   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4631   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);
4632 
4633   PetscCall((*conv)(mat, ftype, f));
4634   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4635   PetscFunctionReturn(0);
4636 }
4637 
4638 /*@C
4639    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4640 
4641    Not Collective
4642 
4643    Input Parameters:
4644 +  mat - the matrix
4645 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4646 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4647 
4648    Output Parameter:
4649 .    flg - PETSC_TRUE if the factorization is available
4650 
4651    Notes:
4652       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4653      such as pastix, superlu, mumps etc.
4654 
4655       PETSc must have been ./configure to use the external solver, using the option --download-package
4656 
4657    Developer Note:
4658       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4659 
4660    Level: intermediate
4661 
4662 .seealso: `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4663           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4664 @*/
4665 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) {
4666   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4667 
4668   PetscFunctionBegin;
4669   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4670   PetscValidType(mat, 1);
4671   PetscValidBoolPointer(flg, 4);
4672 
4673   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4674   MatCheckPreallocated(mat, 1);
4675 
4676   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4677   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4678   PetscFunctionReturn(0);
4679 }
4680 
4681 /*@
4682    MatDuplicate - Duplicates a matrix including the non-zero structure.
4683 
4684    Collective on mat
4685 
4686    Input Parameters:
4687 +  mat - the matrix
4688 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4689         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4690 
4691    Output Parameter:
4692 .  M - pointer to place new matrix
4693 
4694    Level: intermediate
4695 
4696    Notes:
4697     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4698 
4699     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.
4700 
4701     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
4702     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4703     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4704 
4705 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4706 @*/
4707 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) {
4708   Mat         B;
4709   VecType     vtype;
4710   PetscInt    i;
4711   PetscObject dm;
4712   void (*viewf)(void);
4713 
4714   PetscFunctionBegin;
4715   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4716   PetscValidType(mat, 1);
4717   PetscValidPointer(M, 3);
4718   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4719   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4720   MatCheckPreallocated(mat, 1);
4721 
4722   *M = NULL;
4723   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4724   PetscUseTypeMethod(mat, duplicate, op, M);
4725   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4726   B = *M;
4727 
4728   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4729   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4730   PetscCall(MatGetVecType(mat, &vtype));
4731   PetscCall(MatSetVecType(B, vtype));
4732 
4733   B->stencil.dim = mat->stencil.dim;
4734   B->stencil.noc = mat->stencil.noc;
4735   for (i = 0; i <= mat->stencil.dim; i++) {
4736     B->stencil.dims[i]   = mat->stencil.dims[i];
4737     B->stencil.starts[i] = mat->stencil.starts[i];
4738   }
4739 
4740   B->nooffproczerorows = mat->nooffproczerorows;
4741   B->nooffprocentries  = mat->nooffprocentries;
4742 
4743   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4744   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4745   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4746   PetscFunctionReturn(0);
4747 }
4748 
4749 /*@
4750    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4751 
4752    Logically Collective on mat
4753 
4754    Input Parameters:
4755 +  mat - the matrix
4756 -  v - the vector for storing the diagonal
4757 
4758    Output Parameter:
4759 .  v - the diagonal of the matrix
4760 
4761    Level: intermediate
4762 
4763    Note:
4764    Currently only correct in parallel for square matrices.
4765 
4766 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4767 @*/
4768 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) {
4769   PetscFunctionBegin;
4770   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4771   PetscValidType(mat, 1);
4772   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4773   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4774   MatCheckPreallocated(mat, 1);
4775 
4776   PetscUseTypeMethod(mat, getdiagonal, v);
4777   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4778   PetscFunctionReturn(0);
4779 }
4780 
4781 /*@C
4782    MatGetRowMin - Gets the minimum value (of the real part) of each
4783         row of the matrix
4784 
4785    Logically Collective on mat
4786 
4787    Input Parameter:
4788 .  mat - the matrix
4789 
4790    Output Parameters:
4791 +  v - the vector for storing the maximums
4792 -  idx - the indices of the column found for each row (optional)
4793 
4794    Level: intermediate
4795 
4796    Note:
4797     The result of this call are the same as if one converted the matrix to dense format
4798       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4799 
4800     This code is only implemented for a couple of matrix formats.
4801 
4802 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4803           `MatGetRowMax()`
4804 @*/
4805 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) {
4806   PetscFunctionBegin;
4807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4808   PetscValidType(mat, 1);
4809   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4810   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4811 
4812   if (!mat->cmap->N) {
4813     PetscCall(VecSet(v, PETSC_MAX_REAL));
4814     if (idx) {
4815       PetscInt i, m = mat->rmap->n;
4816       for (i = 0; i < m; i++) idx[i] = -1;
4817     }
4818   } else {
4819     MatCheckPreallocated(mat, 1);
4820   }
4821   PetscUseTypeMethod(mat, getrowmin, v, idx);
4822   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4823   PetscFunctionReturn(0);
4824 }
4825 
4826 /*@C
4827    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4828         row of the matrix
4829 
4830    Logically Collective on mat
4831 
4832    Input Parameter:
4833 .  mat - the matrix
4834 
4835    Output Parameters:
4836 +  v - the vector for storing the minimums
4837 -  idx - the indices of the column found for each row (or NULL if not needed)
4838 
4839    Level: intermediate
4840 
4841    Notes:
4842     if a row is completely empty or has only 0.0 values then the idx[] value for that
4843     row is 0 (the first column).
4844 
4845     This code is only implemented for a couple of matrix formats.
4846 
4847 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4848 @*/
4849 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) {
4850   PetscFunctionBegin;
4851   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4852   PetscValidType(mat, 1);
4853   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4854   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4855   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4856 
4857   if (!mat->cmap->N) {
4858     PetscCall(VecSet(v, 0.0));
4859     if (idx) {
4860       PetscInt i, m = mat->rmap->n;
4861       for (i = 0; i < m; i++) idx[i] = -1;
4862     }
4863   } else {
4864     MatCheckPreallocated(mat, 1);
4865     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4866     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4867   }
4868   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4869   PetscFunctionReturn(0);
4870 }
4871 
4872 /*@C
4873    MatGetRowMax - Gets the maximum value (of the real part) of each
4874         row of the matrix
4875 
4876    Logically Collective on mat
4877 
4878    Input Parameter:
4879 .  mat - the matrix
4880 
4881    Output Parameters:
4882 +  v - the vector for storing the maximums
4883 -  idx - the indices of the column found for each row (optional)
4884 
4885    Level: intermediate
4886 
4887    Notes:
4888     The result of this call are the same as if one converted the matrix to dense format
4889       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4890 
4891     This code is only implemented for a couple of matrix formats.
4892 
4893 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4894 @*/
4895 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) {
4896   PetscFunctionBegin;
4897   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4898   PetscValidType(mat, 1);
4899   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4900   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4901 
4902   if (!mat->cmap->N) {
4903     PetscCall(VecSet(v, PETSC_MIN_REAL));
4904     if (idx) {
4905       PetscInt i, m = mat->rmap->n;
4906       for (i = 0; i < m; i++) idx[i] = -1;
4907     }
4908   } else {
4909     MatCheckPreallocated(mat, 1);
4910     PetscUseTypeMethod(mat, getrowmax, v, idx);
4911   }
4912   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4913   PetscFunctionReturn(0);
4914 }
4915 
4916 /*@C
4917    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4918         row of the matrix
4919 
4920    Logically Collective on mat
4921 
4922    Input Parameter:
4923 .  mat - the matrix
4924 
4925    Output Parameters:
4926 +  v - the vector for storing the maximums
4927 -  idx - the indices of the column found for each row (or NULL if not needed)
4928 
4929    Level: intermediate
4930 
4931    Notes:
4932     if a row is completely empty or has only 0.0 values then the idx[] value for that
4933     row is 0 (the first column).
4934 
4935     This code is only implemented for a couple of matrix formats.
4936 
4937 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4938 @*/
4939 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) {
4940   PetscFunctionBegin;
4941   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4942   PetscValidType(mat, 1);
4943   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4944   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4945 
4946   if (!mat->cmap->N) {
4947     PetscCall(VecSet(v, 0.0));
4948     if (idx) {
4949       PetscInt i, m = mat->rmap->n;
4950       for (i = 0; i < m; i++) idx[i] = -1;
4951     }
4952   } else {
4953     MatCheckPreallocated(mat, 1);
4954     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4955     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
4956   }
4957   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4958   PetscFunctionReturn(0);
4959 }
4960 
4961 /*@
4962    MatGetRowSum - Gets the sum of each row of the matrix
4963 
4964    Logically or Neighborhood Collective on mat
4965 
4966    Input Parameters:
4967 .  mat - the matrix
4968 
4969    Output Parameter:
4970 .  v - the vector for storing the sum of rows
4971 
4972    Level: intermediate
4973 
4974    Notes:
4975     This code is slow since it is not currently specialized for different formats
4976 
4977 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
4978 @*/
4979 PetscErrorCode MatGetRowSum(Mat mat, Vec v) {
4980   Vec ones;
4981 
4982   PetscFunctionBegin;
4983   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4984   PetscValidType(mat, 1);
4985   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4986   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4987   MatCheckPreallocated(mat, 1);
4988   PetscCall(MatCreateVecs(mat, &ones, NULL));
4989   PetscCall(VecSet(ones, 1.));
4990   PetscCall(MatMult(mat, ones, v));
4991   PetscCall(VecDestroy(&ones));
4992   PetscFunctionReturn(0);
4993 }
4994 
4995 /*@
4996    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
4997    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
4998 
4999    Collective on mat
5000 
5001    Input Parameter:
5002 .  mat - the matrix to provide the transpose
5003 
5004    Output Parameter:
5005 .  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
5006 
5007    Level: advanced
5008 
5009    Note:
5010    Normally he use of `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B) requires that B was obtained with a call to `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B). This
5011    routine allows bypassing that call.
5012 
5013 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5014 @*/
5015 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) {
5016   PetscContainer  rB = NULL;
5017   MatParentState *rb = NULL;
5018 
5019   PetscFunctionBegin;
5020   PetscCall(PetscNew(&rb));
5021   rb->id    = ((PetscObject)mat)->id;
5022   rb->state = 0;
5023   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5024   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5025   PetscCall(PetscContainerSetPointer(rB, rb));
5026   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5027   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5028   PetscCall(PetscObjectDereference((PetscObject)rB));
5029   PetscFunctionReturn(0);
5030 }
5031 
5032 /*@
5033    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5034 
5035    Collective on mat
5036 
5037    Input Parameters:
5038 +  mat - the matrix to transpose
5039 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5040 
5041    Output Parameter:
5042 .  B - the transpose
5043 
5044    Notes:
5045      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5046 
5047      `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
5048      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5049 
5050      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.
5051 
5052      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5053 
5054      If mat is unchanged from the last call this function returns immediately without recomputing the result
5055 
5056      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5057 
5058    Level: intermediate
5059 
5060 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5061           `MatTransposeSymbolic()`
5062 @*/
5063 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) {
5064   PetscContainer  rB = NULL;
5065   MatParentState *rb = NULL;
5066 
5067   PetscFunctionBegin;
5068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5069   PetscValidType(mat, 1);
5070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5071   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5072   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5073   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5074   MatCheckPreallocated(mat, 1);
5075   if (reuse == MAT_REUSE_MATRIX) {
5076     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5077     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5078     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5079     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5080     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0);
5081   }
5082 
5083   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5084   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5085     PetscUseTypeMethod(mat, transpose, reuse, B);
5086     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5087   }
5088   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5089 
5090   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5091   if (reuse != MAT_INPLACE_MATRIX) {
5092     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5093     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5094     rb->state        = ((PetscObject)mat)->state;
5095     rb->nonzerostate = mat->nonzerostate;
5096   }
5097   PetscFunctionReturn(0);
5098 }
5099 
5100 /*@
5101    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5102 
5103    Collective on A
5104 
5105    Input Parameters:
5106 .  A - the matrix to transpose
5107 
5108    Output Parameter:
5109 .  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
5110       numerical portion.
5111 
5112    Level: intermediate
5113 
5114    Note:
5115    This is not supported for many matrix types, use `MatTranspose()` in those cases
5116 
5117 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5118 @*/
5119 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) {
5120   PetscFunctionBegin;
5121   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5122   PetscValidType(A, 1);
5123   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5124   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5125   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5126   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5127   PetscCall((*A->ops->transposesymbolic)(A, B));
5128   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5129 
5130   PetscCall(MatTransposeSetPrecursor(A, *B));
5131   PetscFunctionReturn(0);
5132 }
5133 
5134 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) {
5135   PetscContainer  rB;
5136   MatParentState *rb;
5137 
5138   PetscFunctionBegin;
5139   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5140   PetscValidType(A, 1);
5141   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5142   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5143   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5144   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5145   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5146   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5147   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5148   PetscFunctionReturn(0);
5149 }
5150 
5151 /*@
5152    MatIsTranspose - Test whether a matrix is another one's transpose,
5153         or its own, in which case it tests symmetry.
5154 
5155    Collective on A
5156 
5157    Input Parameters:
5158 +  A - the matrix to test
5159 -  B - the matrix to test against, this can equal the first parameter
5160 
5161    Output Parameters:
5162 .  flg - the result
5163 
5164    Notes:
5165    Only available for `MATAIJ` matrices.
5166 
5167    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5168    test involves parallel copies of the block-offdiagonal parts of the matrix.
5169 
5170    Level: intermediate
5171 
5172 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5173 @*/
5174 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) {
5175   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5176 
5177   PetscFunctionBegin;
5178   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5179   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5180   PetscValidBoolPointer(flg, 4);
5181   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5182   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5183   *flg = PETSC_FALSE;
5184   if (f && g) {
5185     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5186     PetscCall((*f)(A, B, tol, flg));
5187   } else {
5188     MatType mattype;
5189 
5190     PetscCall(MatGetType(f ? B : A, &mattype));
5191     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5192   }
5193   PetscFunctionReturn(0);
5194 }
5195 
5196 /*@
5197    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5198 
5199    Collective on mat
5200 
5201    Input Parameters:
5202 +  mat - the matrix to transpose and complex conjugate
5203 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5204 
5205    Output Parameter:
5206 .  B - the Hermitian transpose
5207 
5208    Level: intermediate
5209 
5210 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5211 @*/
5212 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) {
5213   PetscFunctionBegin;
5214   PetscCall(MatTranspose(mat, reuse, B));
5215 #if defined(PETSC_USE_COMPLEX)
5216   PetscCall(MatConjugate(*B));
5217 #endif
5218   PetscFunctionReturn(0);
5219 }
5220 
5221 /*@
5222    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5223 
5224    Collective on A
5225 
5226    Input Parameters:
5227 +  A - the matrix to test
5228 -  B - the matrix to test against, this can equal the first parameter
5229 
5230    Output Parameters:
5231 .  flg - the result
5232 
5233    Notes:
5234    Only available for `MATAIJ` matrices.
5235 
5236    The sequential algorithm
5237    has a running time of the order of the number of nonzeros; the parallel
5238    test involves parallel copies of the block-offdiagonal parts of the matrix.
5239 
5240    Level: intermediate
5241 
5242 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5243 @*/
5244 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) {
5245   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5246 
5247   PetscFunctionBegin;
5248   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5249   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5250   PetscValidBoolPointer(flg, 4);
5251   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5252   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5253   if (f && g) {
5254     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5255     PetscCall((*f)(A, B, tol, flg));
5256   }
5257   PetscFunctionReturn(0);
5258 }
5259 
5260 /*@
5261    MatPermute - Creates a new matrix with rows and columns permuted from the
5262    original.
5263 
5264    Collective on mat
5265 
5266    Input Parameters:
5267 +  mat - the matrix to permute
5268 .  row - row permutation, each processor supplies only the permutation for its rows
5269 -  col - column permutation, each processor supplies only the permutation for its columns
5270 
5271    Output Parameters:
5272 .  B - the permuted matrix
5273 
5274    Level: advanced
5275 
5276    Note:
5277    The index sets map from row/col of permuted matrix to row/col of original matrix.
5278    The index sets should be on the same communicator as mat and have the same local sizes.
5279 
5280    Developer Note:
5281      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5282      exploit the fact that row and col are permutations, consider implementing the
5283      more general `MatCreateSubMatrix()` instead.
5284 
5285 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5286 @*/
5287 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) {
5288   PetscFunctionBegin;
5289   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5290   PetscValidType(mat, 1);
5291   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5292   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5293   PetscValidPointer(B, 4);
5294   PetscCheckSameComm(mat, 1, row, 2);
5295   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5296   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5297   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5298   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5299   MatCheckPreallocated(mat, 1);
5300 
5301   if (mat->ops->permute) {
5302     PetscUseTypeMethod(mat, permute, row, col, B);
5303     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5304   } else {
5305     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5306   }
5307   PetscFunctionReturn(0);
5308 }
5309 
5310 /*@
5311    MatEqual - Compares two matrices.
5312 
5313    Collective on A
5314 
5315    Input Parameters:
5316 +  A - the first matrix
5317 -  B - the second matrix
5318 
5319    Output Parameter:
5320 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5321 
5322    Level: intermediate
5323 
5324 .seealso: `Mat`
5325 @*/
5326 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) {
5327   PetscFunctionBegin;
5328   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5329   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5330   PetscValidType(A, 1);
5331   PetscValidType(B, 2);
5332   PetscValidBoolPointer(flg, 3);
5333   PetscCheckSameComm(A, 1, B, 2);
5334   MatCheckPreallocated(A, 1);
5335   MatCheckPreallocated(B, 2);
5336   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5337   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5338   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,
5339              B->cmap->N);
5340   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5341     PetscUseTypeMethod(A, equal, B, flg);
5342   } else {
5343     PetscCall(MatMultEqual(A, B, 10, flg));
5344   }
5345   PetscFunctionReturn(0);
5346 }
5347 
5348 /*@
5349    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5350    matrices that are stored as vectors.  Either of the two scaling
5351    matrices can be NULL.
5352 
5353    Collective on mat
5354 
5355    Input Parameters:
5356 +  mat - the matrix to be scaled
5357 .  l - the left scaling vector (or NULL)
5358 -  r - the right scaling vector (or NULL)
5359 
5360    Note:
5361    `MatDiagonalScale()` computes A = LAR, where
5362    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5363    The L scales the rows of the matrix, the R scales the columns of the matrix.
5364 
5365    Level: intermediate
5366 
5367 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5368 @*/
5369 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) {
5370   PetscFunctionBegin;
5371   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5372   PetscValidType(mat, 1);
5373   if (l) {
5374     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5375     PetscCheckSameComm(mat, 1, l, 2);
5376   }
5377   if (r) {
5378     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5379     PetscCheckSameComm(mat, 1, r, 3);
5380   }
5381   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5382   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5383   MatCheckPreallocated(mat, 1);
5384   if (!l && !r) PetscFunctionReturn(0);
5385 
5386   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5387   PetscUseTypeMethod(mat, diagonalscale, l, r);
5388   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5389   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5390   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5391   PetscFunctionReturn(0);
5392 }
5393 
5394 /*@
5395     MatScale - Scales all elements of a matrix by a given number.
5396 
5397     Logically Collective on mat
5398 
5399     Input Parameters:
5400 +   mat - the matrix to be scaled
5401 -   a  - the scaling value
5402 
5403     Output Parameter:
5404 .   mat - the scaled matrix
5405 
5406     Level: intermediate
5407 
5408 .seealso: `Mat`, `MatDiagonalScale()`
5409 @*/
5410 PetscErrorCode MatScale(Mat mat, PetscScalar a) {
5411   PetscFunctionBegin;
5412   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5413   PetscValidType(mat, 1);
5414   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5415   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5416   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5417   PetscValidLogicalCollectiveScalar(mat, a, 2);
5418   MatCheckPreallocated(mat, 1);
5419 
5420   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5421   if (a != (PetscScalar)1.0) {
5422     PetscUseTypeMethod(mat, scale, a);
5423     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5424   }
5425   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5426   PetscFunctionReturn(0);
5427 }
5428 
5429 /*@
5430    MatNorm - Calculates various norms of a matrix.
5431 
5432    Collective on mat
5433 
5434    Input Parameters:
5435 +  mat - the matrix
5436 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5437 
5438    Output Parameter:
5439 .  nrm - the resulting norm
5440 
5441    Level: intermediate
5442 
5443 .seealso: `Mat`
5444 @*/
5445 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) {
5446   PetscFunctionBegin;
5447   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5448   PetscValidType(mat, 1);
5449   PetscValidRealPointer(nrm, 3);
5450 
5451   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5452   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5453   MatCheckPreallocated(mat, 1);
5454 
5455   PetscUseTypeMethod(mat, norm, type, nrm);
5456   PetscFunctionReturn(0);
5457 }
5458 
5459 /*
5460      This variable is used to prevent counting of MatAssemblyBegin() that
5461    are called from within a MatAssemblyEnd().
5462 */
5463 static PetscInt MatAssemblyEnd_InUse = 0;
5464 /*@
5465    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5466    be called after completing all calls to `MatSetValues()`.
5467 
5468    Collective on mat
5469 
5470    Input Parameters:
5471 +  mat - the matrix
5472 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5473 
5474    Notes:
5475    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5476    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5477 
5478    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5479    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5480    using the matrix.
5481 
5482    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5483    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
5484    a global collective operation requring all processes that share the matrix.
5485 
5486    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5487    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5488    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5489 
5490    Level: beginner
5491 
5492 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5493 @*/
5494 PetscErrorCode  MatAssemblyBegin(Mat mat, MatAssemblyType type) {
5495    PetscFunctionBegin;
5496    PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5497    PetscValidType(mat, 1);
5498    MatCheckPreallocated(mat, 1);
5499    PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5500    if (mat->assembled) {
5501      mat->was_assembled = PETSC_TRUE;
5502      mat->assembled     = PETSC_FALSE;
5503   }
5504 
5505    if (!MatAssemblyEnd_InUse) {
5506      PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5507      PetscTryTypeMethod(mat, assemblybegin, type);
5508      PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5509   } else PetscTryTypeMethod(mat, assemblybegin, type);
5510    PetscFunctionReturn(0);
5511 }
5512 
5513 /*@
5514    MatAssembled - Indicates if a matrix has been assembled and is ready for
5515      use; for example, in matrix-vector product.
5516 
5517    Not Collective
5518 
5519    Input Parameter:
5520 .  mat - the matrix
5521 
5522    Output Parameter:
5523 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5524 
5525    Level: advanced
5526 
5527 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5528 @*/
5529 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) {
5530   PetscFunctionBegin;
5531   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5532   PetscValidBoolPointer(assembled, 2);
5533   *assembled = mat->assembled;
5534   PetscFunctionReturn(0);
5535 }
5536 
5537 /*@
5538    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5539    be called after `MatAssemblyBegin()`.
5540 
5541    Collective on Mat
5542 
5543    Input Parameters:
5544 +  mat - the matrix
5545 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5546 
5547    Options Database Keys:
5548 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5549 .  -mat_view ::ascii_info_detail - Prints more detailed info
5550 .  -mat_view - Prints matrix in ASCII format
5551 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5552 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5553 .  -display <name> - Sets display name (default is host)
5554 .  -draw_pause <sec> - Sets number of seconds to pause after display
5555 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab)
5556 .  -viewer_socket_machine <machine> - Machine to use for socket
5557 .  -viewer_socket_port <port> - Port number to use for socket
5558 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5559 
5560    Level: beginner
5561 
5562 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5563 @*/
5564 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) {
5565   static PetscInt inassm = 0;
5566   PetscBool       flg    = PETSC_FALSE;
5567 
5568   PetscFunctionBegin;
5569   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5570   PetscValidType(mat, 1);
5571 
5572   inassm++;
5573   MatAssemblyEnd_InUse++;
5574   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5575     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5576     PetscTryTypeMethod(mat, assemblyend, type);
5577     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5578   } else PetscTryTypeMethod(mat, assemblyend, type);
5579 
5580   /* Flush assembly is not a true assembly */
5581   if (type != MAT_FLUSH_ASSEMBLY) {
5582     if (mat->num_ass) {
5583       if (!mat->symmetry_eternal) {
5584         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5585         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5586       }
5587       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5588       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5589     }
5590     mat->num_ass++;
5591     mat->assembled        = PETSC_TRUE;
5592     mat->ass_nonzerostate = mat->nonzerostate;
5593   }
5594 
5595   mat->insertmode = NOT_SET_VALUES;
5596   MatAssemblyEnd_InUse--;
5597   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5598   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5599     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5600 
5601     if (mat->checksymmetryonassembly) {
5602       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5603       if (flg) {
5604         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5605       } else {
5606         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5607       }
5608     }
5609     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5610   }
5611   inassm--;
5612   PetscFunctionReturn(0);
5613 }
5614 
5615 /*@
5616    MatSetOption - Sets a parameter option for a matrix. Some options
5617    may be specific to certain storage formats.  Some options
5618    determine how values will be inserted (or added). Sorted,
5619    row-oriented input will generally assemble the fastest. The default
5620    is row-oriented.
5621 
5622    Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5623 
5624    Input Parameters:
5625 +  mat - the matrix
5626 .  option - the option, one of those listed below (and possibly others),
5627 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5628 
5629   Options Describing Matrix Structure:
5630 +    `MAT_SPD` - symmetric positive definite
5631 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5632 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5633 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5634 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5635 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5636 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5637 
5638    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5639    do not need to be computed (usually at a high cost)
5640 
5641    Options For Use with `MatSetValues()`:
5642    Insert a logically dense subblock, which can be
5643 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5644 
5645    Note these options reflect the data you pass in with `MatSetValues()`; it has
5646    nothing to do with how the data is stored internally in the matrix
5647    data structure.
5648 
5649    When (re)assembling a matrix, we can restrict the input for
5650    efficiency/debugging purposes.  These options include
5651 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5652 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5653 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5654 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5655 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5656 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5657         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5658         performance for very large process counts.
5659 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5660         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5661         functions, instead sending only neighbor messages.
5662 
5663    Notes:
5664    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5665 
5666    Some options are relevant only for particular matrix types and
5667    are thus ignored by others.  Other options are not supported by
5668    certain matrix types and will generate an error message if set.
5669 
5670    If using a Fortran 77 module to compute a matrix, one may need to
5671    use the column-oriented option (or convert to the row-oriented
5672    format).
5673 
5674    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5675    that would generate a new entry in the nonzero structure is instead
5676    ignored.  Thus, if memory has not alredy been allocated for this particular
5677    data, then the insertion is ignored. For dense matrices, in which
5678    the entire array is allocated, no entries are ever ignored.
5679    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5680 
5681    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5682    that would generate a new entry in the nonzero structure instead produces
5683    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
5684 
5685    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5686    that would generate a new entry that has not been preallocated will
5687    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5688    only.) This is a useful flag when debugging matrix memory preallocation.
5689    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5690 
5691    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5692    other processors should be dropped, rather than stashed.
5693    This is useful if you know that the "owning" processor is also
5694    always generating the correct matrix entries, so that PETSc need
5695    not transfer duplicate entries generated on another processor.
5696 
5697    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5698    searches during matrix assembly. When this flag is set, the hash table
5699    is created during the first matrix assembly. This hash table is
5700    used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5701    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5702    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5703    supported by` MATMPIBAIJ` format only.
5704 
5705    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5706    are kept in the nonzero structure
5707 
5708    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5709    a zero location in the matrix
5710 
5711    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5712 
5713    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5714         zero row routines and thus improves performance for very large process counts.
5715 
5716    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5717         part of the matrix (since they should match the upper triangular part).
5718 
5719    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5720                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5721                      with finite difference schemes with non-periodic boundary conditions.
5722 
5723    Developer Note:
5724    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5725    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5726    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5727    not changed.
5728 
5729    Level: intermediate
5730 
5731 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5732 @*/
5733 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) {
5734   PetscFunctionBegin;
5735   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5736   if (op > 0) {
5737     PetscValidLogicalCollectiveEnum(mat, op, 2);
5738     PetscValidLogicalCollectiveBool(mat, flg, 3);
5739   }
5740 
5741   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);
5742 
5743   switch (op) {
5744   case MAT_FORCE_DIAGONAL_ENTRIES: mat->force_diagonals = flg; PetscFunctionReturn(0);
5745   case MAT_NO_OFF_PROC_ENTRIES: mat->nooffprocentries = flg; PetscFunctionReturn(0);
5746   case MAT_SUBSET_OFF_PROC_ENTRIES:
5747     mat->assembly_subset = flg;
5748     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5749 #if !defined(PETSC_HAVE_MPIUNI)
5750       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5751 #endif
5752       mat->stash.first_assembly_done = PETSC_FALSE;
5753     }
5754     PetscFunctionReturn(0);
5755   case MAT_NO_OFF_PROC_ZERO_ROWS: mat->nooffproczerorows = flg; PetscFunctionReturn(0);
5756   case MAT_SPD:
5757     if (flg) {
5758       mat->spd                    = PETSC_BOOL3_TRUE;
5759       mat->symmetric              = PETSC_BOOL3_TRUE;
5760       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5761     } else {
5762       mat->spd = PETSC_BOOL3_FALSE;
5763     }
5764     break;
5765   case MAT_SYMMETRIC:
5766     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5767     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5768 #if !defined(PETSC_USE_COMPLEX)
5769     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5770 #endif
5771     break;
5772   case MAT_HERMITIAN:
5773     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5774     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5775 #if !defined(PETSC_USE_COMPLEX)
5776     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5777 #endif
5778     break;
5779   case MAT_STRUCTURALLY_SYMMETRIC: mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; break;
5780   case MAT_SYMMETRY_ETERNAL:
5781     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");
5782     mat->symmetry_eternal = flg;
5783     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5784     break;
5785   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5786     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");
5787     mat->structural_symmetry_eternal = flg;
5788     break;
5789   case MAT_SPD_ETERNAL:
5790     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");
5791     mat->spd_eternal = flg;
5792     if (flg) {
5793       mat->structural_symmetry_eternal = PETSC_TRUE;
5794       mat->symmetry_eternal            = PETSC_TRUE;
5795     }
5796     break;
5797   case MAT_STRUCTURE_ONLY: mat->structure_only = flg; break;
5798   case MAT_SORTED_FULL: mat->sortedfull = flg; break;
5799   default: break;
5800   }
5801   PetscTryTypeMethod(mat, setoption, op, flg);
5802   PetscFunctionReturn(0);
5803 }
5804 
5805 /*@
5806    MatGetOption - Gets a parameter option that has been set for a matrix.
5807 
5808    Logically Collective on mat
5809 
5810    Input Parameters:
5811 +  mat - the matrix
5812 -  option - the option, this only responds to certain options, check the code for which ones
5813 
5814    Output Parameter:
5815 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5816 
5817     Notes:
5818     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5819 
5820     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`, or
5821     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5822 
5823    Level: intermediate
5824 
5825 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`,
5826     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5827 @*/
5828 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) {
5829   PetscFunctionBegin;
5830   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5831   PetscValidType(mat, 1);
5832 
5833   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);
5834   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()");
5835 
5836   switch (op) {
5837   case MAT_NO_OFF_PROC_ENTRIES: *flg = mat->nooffprocentries; break;
5838   case MAT_NO_OFF_PROC_ZERO_ROWS: *flg = mat->nooffproczerorows; break;
5839   case MAT_SYMMETRIC: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); break;
5840   case MAT_HERMITIAN: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); break;
5841   case MAT_STRUCTURALLY_SYMMETRIC: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); break;
5842   case MAT_SPD: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); break;
5843   case MAT_SYMMETRY_ETERNAL: *flg = mat->symmetry_eternal; break;
5844   case MAT_STRUCTURAL_SYMMETRY_ETERNAL: *flg = mat->symmetry_eternal; break;
5845   default: break;
5846   }
5847   PetscFunctionReturn(0);
5848 }
5849 
5850 /*@
5851    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5852    this routine retains the old nonzero structure.
5853 
5854    Logically Collective on mat
5855 
5856    Input Parameters:
5857 .  mat - the matrix
5858 
5859    Level: intermediate
5860 
5861    Note:
5862     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.
5863    See the Performance chapter of the users manual for information on preallocating matrices.
5864 
5865 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5866 @*/
5867 PetscErrorCode MatZeroEntries(Mat mat) {
5868   PetscFunctionBegin;
5869   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5870   PetscValidType(mat, 1);
5871   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5872   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");
5873   MatCheckPreallocated(mat, 1);
5874 
5875   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
5876   PetscUseTypeMethod(mat, zeroentries);
5877   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
5878   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5879   PetscFunctionReturn(0);
5880 }
5881 
5882 /*@
5883    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5884    of a set of rows and columns of a matrix.
5885 
5886    Collective on mat
5887 
5888    Input Parameters:
5889 +  mat - the matrix
5890 .  numRows - the number of rows to remove
5891 .  rows - the global row indices
5892 .  diag - value put in the diagonal of the eliminated rows
5893 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5894 -  b - optional vector of right hand side, that will be adjusted by provided solution
5895 
5896    Notes:
5897    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5898 
5899    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5900    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
5901 
5902    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5903    Krylov method to take advantage of the known solution on the zeroed rows.
5904 
5905    For the parallel case, all processes that share the matrix (i.e.,
5906    those in the communicator used for matrix creation) MUST call this
5907    routine, regardless of whether any rows being zeroed are owned by
5908    them.
5909 
5910    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5911 
5912    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5913    list only rows local to itself).
5914 
5915    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
5916 
5917    Level: intermediate
5918 
5919 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5920           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5921 @*/
5922 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
5923   PetscFunctionBegin;
5924   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5925   PetscValidType(mat, 1);
5926   if (numRows) PetscValidIntPointer(rows, 3);
5927   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5928   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5929   MatCheckPreallocated(mat, 1);
5930 
5931   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5932   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5933   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5934   PetscFunctionReturn(0);
5935 }
5936 
5937 /*@
5938    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5939    of a set of rows and columns of a matrix.
5940 
5941    Collective on mat
5942 
5943    Input Parameters:
5944 +  mat - the matrix
5945 .  is - the rows to zero
5946 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5947 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5948 -  b - optional vector of right hand side, that will be adjusted by provided solution
5949 
5950    Note:
5951    See `MatZeroRowsColumns()` for details on how this routine operates.
5952 
5953    Level: intermediate
5954 
5955 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5956           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
5957 @*/
5958 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
5959   PetscInt        numRows;
5960   const PetscInt *rows;
5961 
5962   PetscFunctionBegin;
5963   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5964   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
5965   PetscValidType(mat, 1);
5966   PetscValidType(is, 2);
5967   PetscCall(ISGetLocalSize(is, &numRows));
5968   PetscCall(ISGetIndices(is, &rows));
5969   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
5970   PetscCall(ISRestoreIndices(is, &rows));
5971   PetscFunctionReturn(0);
5972 }
5973 
5974 /*@
5975    MatZeroRows - Zeros all entries (except possibly the main diagonal)
5976    of a set of rows of a matrix.
5977 
5978    Collective on mat
5979 
5980    Input Parameters:
5981 +  mat - the matrix
5982 .  numRows - the number of rows to remove
5983 .  rows - the global row indices
5984 .  diag - value put in the diagonal of the eliminated rows
5985 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5986 -  b - optional vector of right hand side, that will be adjusted by provided solution
5987 
5988    Notes:
5989    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5990 
5991    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5992 
5993    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5994    Krylov method to take advantage of the known solution on the zeroed rows.
5995 
5996    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reducing problem (after completely eliminating the zeroed rows and their corresponding columns)
5997    from the matrix.
5998 
5999    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6000    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
6001    formats this does not alter the nonzero structure.
6002 
6003    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6004    of the matrix is not changed the values are
6005    merely zeroed.
6006 
6007    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6008    formats can optionally remove the main diagonal entry from the
6009    nonzero structure as well, by passing 0.0 as the final argument).
6010 
6011    For the parallel case, all processes that share the matrix (i.e.,
6012    those in the communicator used for matrix creation) MUST call this
6013    routine, regardless of whether any rows being zeroed are owned by
6014    them.
6015 
6016    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6017    list only rows local to itself).
6018 
6019    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6020    owns that are to be zeroed. This saves a global synchronization in the implementation.
6021 
6022    Level: intermediate
6023 
6024 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6025           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6026 @*/
6027 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6028   PetscFunctionBegin;
6029   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6030   PetscValidType(mat, 1);
6031   if (numRows) PetscValidIntPointer(rows, 3);
6032   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6033   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6034   MatCheckPreallocated(mat, 1);
6035 
6036   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6037   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6038   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6039   PetscFunctionReturn(0);
6040 }
6041 
6042 /*@
6043    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6044    of a set of rows of a matrix.
6045 
6046    Collective on Mat
6047 
6048    Input Parameters:
6049 +  mat - the matrix
6050 .  is - index set of rows to remove (if NULL then no row is removed)
6051 .  diag - value put in all diagonals of eliminated rows
6052 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6053 -  b - optional vector of right hand side, that will be adjusted by provided solution
6054 
6055    Note:
6056    See `MatZeroRows()` for details on how this routine operates.
6057 
6058    Level: intermediate
6059 
6060 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6061           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6062 @*/
6063 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6064   PetscInt        numRows = 0;
6065   const PetscInt *rows    = NULL;
6066 
6067   PetscFunctionBegin;
6068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6069   PetscValidType(mat, 1);
6070   if (is) {
6071     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6072     PetscCall(ISGetLocalSize(is, &numRows));
6073     PetscCall(ISGetIndices(is, &rows));
6074   }
6075   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6076   if (is) PetscCall(ISRestoreIndices(is, &rows));
6077   PetscFunctionReturn(0);
6078 }
6079 
6080 /*@
6081    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6082    of a set of rows of a matrix. These rows must be local to the process.
6083 
6084    Collective on mat
6085 
6086    Input Parameters:
6087 +  mat - the matrix
6088 .  numRows - the number of rows to remove
6089 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6090 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6091 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6092 -  b - optional vector of right hand side, that will be adjusted by provided solution
6093 
6094    Notes:
6095    See `MatZeroRows()` for details on how this routine operates.
6096 
6097    The grid coordinates are across the entire grid, not just the local portion
6098 
6099    In Fortran idxm and idxn should be declared as
6100 $     MatStencil idxm(4,m)
6101    and the values inserted using
6102 $    idxm(MatStencil_i,1) = i
6103 $    idxm(MatStencil_j,1) = j
6104 $    idxm(MatStencil_k,1) = k
6105 $    idxm(MatStencil_c,1) = c
6106    etc
6107 
6108    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6109    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6110    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6111    `DM_BOUNDARY_PERIODIC` boundary type.
6112 
6113    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
6114    a single value per point) you can skip filling those indices.
6115 
6116    Level: intermediate
6117 
6118 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6119           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6120 @*/
6121 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) {
6122   PetscInt  dim    = mat->stencil.dim;
6123   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6124   PetscInt *dims   = mat->stencil.dims + 1;
6125   PetscInt *starts = mat->stencil.starts;
6126   PetscInt *dxm    = (PetscInt *)rows;
6127   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6128 
6129   PetscFunctionBegin;
6130   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6131   PetscValidType(mat, 1);
6132   if (numRows) PetscValidPointer(rows, 3);
6133 
6134   PetscCall(PetscMalloc1(numRows, &jdxm));
6135   for (i = 0; i < numRows; ++i) {
6136     /* Skip unused dimensions (they are ordered k, j, i, c) */
6137     for (j = 0; j < 3 - sdim; ++j) dxm++;
6138     /* Local index in X dir */
6139     tmp = *dxm++ - starts[0];
6140     /* Loop over remaining dimensions */
6141     for (j = 0; j < dim - 1; ++j) {
6142       /* If nonlocal, set index to be negative */
6143       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6144       /* Update local index */
6145       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6146     }
6147     /* Skip component slot if necessary */
6148     if (mat->stencil.noc) dxm++;
6149     /* Local row number */
6150     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6151   }
6152   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6153   PetscCall(PetscFree(jdxm));
6154   PetscFunctionReturn(0);
6155 }
6156 
6157 /*@
6158    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6159    of a set of rows and columns of a matrix.
6160 
6161    Collective on mat
6162 
6163    Input Parameters:
6164 +  mat - the matrix
6165 .  numRows - the number of rows/columns to remove
6166 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6167 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6168 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6169 -  b - optional vector of right hand side, that will be adjusted by provided solution
6170 
6171    Notes:
6172    See `MatZeroRowsColumns()` for details on how this routine operates.
6173 
6174    The grid coordinates are across the entire grid, not just the local portion
6175 
6176    In Fortran idxm and idxn should be declared as
6177 $     MatStencil idxm(4,m)
6178    and the values inserted using
6179 $    idxm(MatStencil_i,1) = i
6180 $    idxm(MatStencil_j,1) = j
6181 $    idxm(MatStencil_k,1) = k
6182 $    idxm(MatStencil_c,1) = c
6183    etc
6184 
6185    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6186    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6187    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6188    `DM_BOUNDARY_PERIODIC` boundary type.
6189 
6190    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
6191    a single value per point) you can skip filling those indices.
6192 
6193    Level: intermediate
6194 
6195 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6196           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6197 @*/
6198 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) {
6199   PetscInt  dim    = mat->stencil.dim;
6200   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6201   PetscInt *dims   = mat->stencil.dims + 1;
6202   PetscInt *starts = mat->stencil.starts;
6203   PetscInt *dxm    = (PetscInt *)rows;
6204   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6205 
6206   PetscFunctionBegin;
6207   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6208   PetscValidType(mat, 1);
6209   if (numRows) PetscValidPointer(rows, 3);
6210 
6211   PetscCall(PetscMalloc1(numRows, &jdxm));
6212   for (i = 0; i < numRows; ++i) {
6213     /* Skip unused dimensions (they are ordered k, j, i, c) */
6214     for (j = 0; j < 3 - sdim; ++j) dxm++;
6215     /* Local index in X dir */
6216     tmp = *dxm++ - starts[0];
6217     /* Loop over remaining dimensions */
6218     for (j = 0; j < dim - 1; ++j) {
6219       /* If nonlocal, set index to be negative */
6220       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6221       /* Update local index */
6222       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6223     }
6224     /* Skip component slot if necessary */
6225     if (mat->stencil.noc) dxm++;
6226     /* Local row number */
6227     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6228   }
6229   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6230   PetscCall(PetscFree(jdxm));
6231   PetscFunctionReturn(0);
6232 }
6233 
6234 /*@C
6235    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6236    of a set of rows of a matrix; using local numbering of rows.
6237 
6238    Collective on mat
6239 
6240    Input Parameters:
6241 +  mat - the matrix
6242 .  numRows - the number of rows to remove
6243 .  rows - the local row indices
6244 .  diag - value put in all diagonals of eliminated rows
6245 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6246 -  b - optional vector of right hand side, that will be adjusted by provided solution
6247 
6248    Notes:
6249    Before calling `MatZeroRowsLocal()`, the user must first set the
6250    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6251 
6252    See `MatZeroRows()` for details on how this routine operates.
6253 
6254    Level: intermediate
6255 
6256 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6257           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6258 @*/
6259 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6260   PetscFunctionBegin;
6261   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6262   PetscValidType(mat, 1);
6263   if (numRows) PetscValidIntPointer(rows, 3);
6264   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6265   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6266   MatCheckPreallocated(mat, 1);
6267 
6268   if (mat->ops->zerorowslocal) {
6269     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6270   } else {
6271     IS              is, newis;
6272     const PetscInt *newRows;
6273 
6274     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6275     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6276     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6277     PetscCall(ISGetIndices(newis, &newRows));
6278     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6279     PetscCall(ISRestoreIndices(newis, &newRows));
6280     PetscCall(ISDestroy(&newis));
6281     PetscCall(ISDestroy(&is));
6282   }
6283   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6284   PetscFunctionReturn(0);
6285 }
6286 
6287 /*@
6288    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6289    of a set of rows of a matrix; using local numbering of rows.
6290 
6291    Collective on mat
6292 
6293    Input Parameters:
6294 +  mat - the matrix
6295 .  is - index set of rows to remove
6296 .  diag - value put in all diagonals of eliminated rows
6297 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6298 -  b - optional vector of right hand side, that will be adjusted by provided solution
6299 
6300    Notes:
6301    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6302    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6303 
6304    See `MatZeroRows()` for details on how this routine operates.
6305 
6306    Level: intermediate
6307 
6308 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6309           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6310 @*/
6311 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6312   PetscInt        numRows;
6313   const PetscInt *rows;
6314 
6315   PetscFunctionBegin;
6316   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6317   PetscValidType(mat, 1);
6318   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6319   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6320   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6321   MatCheckPreallocated(mat, 1);
6322 
6323   PetscCall(ISGetLocalSize(is, &numRows));
6324   PetscCall(ISGetIndices(is, &rows));
6325   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6326   PetscCall(ISRestoreIndices(is, &rows));
6327   PetscFunctionReturn(0);
6328 }
6329 
6330 /*@
6331    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6332    of a set of rows and columns of a matrix; using local numbering of rows.
6333 
6334    Collective on mat
6335 
6336    Input Parameters:
6337 +  mat - the matrix
6338 .  numRows - the number of rows to remove
6339 .  rows - the global row indices
6340 .  diag - value put in all diagonals of eliminated rows
6341 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6342 -  b - optional vector of right hand side, that will be adjusted by provided solution
6343 
6344    Notes:
6345    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6346    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6347 
6348    See `MatZeroRowsColumns()` for details on how this routine operates.
6349 
6350    Level: intermediate
6351 
6352 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6353           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6354 @*/
6355 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6356   IS              is, newis;
6357   const PetscInt *newRows;
6358 
6359   PetscFunctionBegin;
6360   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6361   PetscValidType(mat, 1);
6362   if (numRows) PetscValidIntPointer(rows, 3);
6363   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6364   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6365   MatCheckPreallocated(mat, 1);
6366 
6367   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6368   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6369   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6370   PetscCall(ISGetIndices(newis, &newRows));
6371   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6372   PetscCall(ISRestoreIndices(newis, &newRows));
6373   PetscCall(ISDestroy(&newis));
6374   PetscCall(ISDestroy(&is));
6375   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6376   PetscFunctionReturn(0);
6377 }
6378 
6379 /*@
6380    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6381    of a set of rows and columns of a matrix; using local numbering of rows.
6382 
6383    Collective on Mat
6384 
6385    Input Parameters:
6386 +  mat - the matrix
6387 .  is - index set of rows to remove
6388 .  diag - value put in all diagonals of eliminated rows
6389 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6390 -  b - optional vector of right hand side, that will be adjusted by provided solution
6391 
6392    Notes:
6393    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6394    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6395 
6396    See `MatZeroRowsColumns()` for details on how this routine operates.
6397 
6398    Level: intermediate
6399 
6400 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6401           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6402 @*/
6403 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6404   PetscInt        numRows;
6405   const PetscInt *rows;
6406 
6407   PetscFunctionBegin;
6408   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6409   PetscValidType(mat, 1);
6410   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6411   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6412   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6413   MatCheckPreallocated(mat, 1);
6414 
6415   PetscCall(ISGetLocalSize(is, &numRows));
6416   PetscCall(ISGetIndices(is, &rows));
6417   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6418   PetscCall(ISRestoreIndices(is, &rows));
6419   PetscFunctionReturn(0);
6420 }
6421 
6422 /*@C
6423    MatGetSize - Returns the numbers of rows and columns in a matrix.
6424 
6425    Not Collective
6426 
6427    Input Parameter:
6428 .  mat - the matrix
6429 
6430    Output Parameters:
6431 +  m - the number of global rows
6432 -  n - the number of global columns
6433 
6434    Note: both output parameters can be NULL on input.
6435 
6436    Level: beginner
6437 
6438 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6439 @*/
6440 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) {
6441   PetscFunctionBegin;
6442   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6443   if (m) *m = mat->rmap->N;
6444   if (n) *n = mat->cmap->N;
6445   PetscFunctionReturn(0);
6446 }
6447 
6448 /*@C
6449    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6450    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6451 
6452    Not Collective
6453 
6454    Input Parameter:
6455 .  mat - the matrix
6456 
6457    Output Parameters:
6458 +  m - the number of local rows, use `NULL` to not obtain this value
6459 -  n - the number of local columns, use `NULL` to not obtain this value
6460 
6461    Level: beginner
6462 
6463 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6464 @*/
6465 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) {
6466   PetscFunctionBegin;
6467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6468   if (m) PetscValidIntPointer(m, 2);
6469   if (n) PetscValidIntPointer(n, 3);
6470   if (m) *m = mat->rmap->n;
6471   if (n) *n = mat->cmap->n;
6472   PetscFunctionReturn(0);
6473 }
6474 
6475 /*@C
6476    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6477    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6478 
6479    Not Collective, unless matrix has not been allocated, then collective on mat
6480 
6481    Input Parameter:
6482 .  mat - the matrix
6483 
6484    Output Parameters:
6485 +  m - the global index of the first local column, use `NULL` to not obtain this value
6486 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6487 
6488    Level: developer
6489 
6490 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6491 @*/
6492 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) {
6493   PetscFunctionBegin;
6494   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6495   PetscValidType(mat, 1);
6496   if (m) PetscValidIntPointer(m, 2);
6497   if (n) PetscValidIntPointer(n, 3);
6498   MatCheckPreallocated(mat, 1);
6499   if (m) *m = mat->cmap->rstart;
6500   if (n) *n = mat->cmap->rend;
6501   PetscFunctionReturn(0);
6502 }
6503 
6504 /*@C
6505    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6506    this MPI rank. For all matrices  it returns the range of matrix rows associated with rows of a vector that would contain the result of a matrix
6507    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6508 
6509    Not Collective
6510 
6511    Input Parameter:
6512 .  mat - the matrix
6513 
6514    Output Parameters:
6515 +  m - the global index of the first local row, use `NULL` to not obtain this value
6516 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6517 
6518    Note:
6519   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6520   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6521   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6522 
6523    Level: beginner
6524 
6525 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6526           `PetscLayout`
6527 @*/
6528 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) {
6529   PetscFunctionBegin;
6530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6531   PetscValidType(mat, 1);
6532   if (m) PetscValidIntPointer(m, 2);
6533   if (n) PetscValidIntPointer(n, 3);
6534   MatCheckPreallocated(mat, 1);
6535   if (m) *m = mat->rmap->rstart;
6536   if (n) *n = mat->rmap->rend;
6537   PetscFunctionReturn(0);
6538 }
6539 
6540 /*@C
6541    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6542    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
6543    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6544 
6545    Not Collective, unless matrix has not been allocated, then collective on mat
6546 
6547    Input Parameters:
6548 .  mat - the matrix
6549 
6550    Output Parameters:
6551 .  ranges - start of each processors portion plus one more than the total length at the end
6552 
6553    Level: beginner
6554 
6555 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6556 @*/
6557 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) {
6558   PetscFunctionBegin;
6559   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6560   PetscValidType(mat, 1);
6561   MatCheckPreallocated(mat, 1);
6562   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6563   PetscFunctionReturn(0);
6564 }
6565 
6566 /*@C
6567    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6568    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6569 
6570    Not Collective, unless matrix has not been allocated, then collective on Mat
6571 
6572    Input Parameters:
6573 .  mat - the matrix
6574 
6575    Output Parameters:
6576 .  ranges - start of each processors portion plus one more then the total length at the end
6577 
6578    Level: beginner
6579 
6580 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6581 @*/
6582 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) {
6583   PetscFunctionBegin;
6584   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6585   PetscValidType(mat, 1);
6586   MatCheckPreallocated(mat, 1);
6587   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6588   PetscFunctionReturn(0);
6589 }
6590 
6591 /*@C
6592    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6593    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6594    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6595 
6596    Not Collective
6597 
6598    Input Parameter:
6599 .  A - matrix
6600 
6601    Output Parameters:
6602 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6603 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6604 
6605    Level: intermediate
6606 
6607 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6608 @*/
6609 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) {
6610   PetscErrorCode (*f)(Mat, IS *, IS *);
6611 
6612   PetscFunctionBegin;
6613   MatCheckPreallocated(A, 1);
6614   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6615   if (f) {
6616     PetscCall((*f)(A, rows, cols));
6617   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6618     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6619     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6620   }
6621   PetscFunctionReturn(0);
6622 }
6623 
6624 /*@C
6625    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6626    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6627    to complete the factorization.
6628 
6629    Collective on fact
6630 
6631    Input Parameters:
6632 +  fact - the factorized matrix obtained with `MatGetFactor()`
6633 .  mat - the matrix
6634 .  row - row permutation
6635 .  column - column permutation
6636 -  info - structure containing
6637 $      levels - number of levels of fill.
6638 $      expected fill - as ratio of original fill.
6639 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6640                 missing diagonal entries)
6641 
6642    Output Parameters:
6643 .  fact - new matrix that has been symbolically factored
6644 
6645    Level: developer
6646 
6647    Notes:
6648    See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
6649 
6650    Most users should employ the `KSP` interface for linear solvers
6651    instead of working directly with matrix algebra routines such as this.
6652    See, e.g., `KSPCreate()`.
6653 
6654    Uses the definition of level of fill as in Y. Saad, 2003
6655 
6656    Developer Note:
6657    The Fortran interface is not autogenerated as the f90
6658    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6659 
6660    References:
6661 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6662 
6663 .seealso: `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6664           `MatGetOrdering()`, `MatFactorInfo`
6665 @*/
6666 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) {
6667   PetscFunctionBegin;
6668   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6669   PetscValidType(mat, 2);
6670   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6671   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6672   PetscValidPointer(info, 5);
6673   PetscValidPointer(fact, 1);
6674   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6675   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6676   if (!fact->ops->ilufactorsymbolic) {
6677     MatSolverType stype;
6678     PetscCall(MatFactorGetSolverType(fact, &stype));
6679     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6680   }
6681   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6682   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6683   MatCheckPreallocated(mat, 2);
6684 
6685   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6686   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6687   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6688   PetscFunctionReturn(0);
6689 }
6690 
6691 /*@C
6692    MatICCFactorSymbolic - Performs symbolic incomplete
6693    Cholesky factorization for a symmetric matrix.  Use
6694    `MatCholeskyFactorNumeric()` to complete the factorization.
6695 
6696    Collective on fact
6697 
6698    Input Parameters:
6699 +  fact - the factorized matrix obtained with `MatGetFactor()`
6700 .  mat - the matrix to be factored
6701 .  perm - row and column permutation
6702 -  info - structure containing
6703 $      levels - number of levels of fill.
6704 $      expected fill - as ratio of original fill.
6705 
6706    Output Parameter:
6707 .  fact - the factored matrix
6708 
6709    Level: developer
6710 
6711    Notes:
6712    Most users should employ the `KSP` interface for linear solvers
6713    instead of working directly with matrix algebra routines such as this.
6714    See, e.g., `KSPCreate()`.
6715 
6716    This uses the definition of level of fill as in Y. Saad, 2003
6717 
6718    Developer Note:
6719    The Fortran interface is not autogenerated as the f90
6720    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6721 
6722    References:
6723 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6724 
6725 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6726 @*/
6727 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) {
6728   PetscFunctionBegin;
6729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6730   PetscValidType(mat, 2);
6731   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6732   PetscValidPointer(info, 4);
6733   PetscValidPointer(fact, 1);
6734   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6735   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6736   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6737   if (!(fact)->ops->iccfactorsymbolic) {
6738     MatSolverType stype;
6739     PetscCall(MatFactorGetSolverType(fact, &stype));
6740     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6741   }
6742   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6743   MatCheckPreallocated(mat, 2);
6744 
6745   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6746   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6747   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6748   PetscFunctionReturn(0);
6749 }
6750 
6751 /*@C
6752    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6753    points to an array of valid matrices, they may be reused to store the new
6754    submatrices.
6755 
6756    Collective on mat
6757 
6758    Input Parameters:
6759 +  mat - the matrix
6760 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6761 .  irow, icol - index sets of rows and columns to extract
6762 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6763 
6764    Output Parameter:
6765 .  submat - the array of submatrices
6766 
6767    Notes:
6768    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6769    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6770    to extract a parallel submatrix.
6771 
6772    Some matrix types place restrictions on the row and column
6773    indices, such as that they be sorted or that they be equal to each other.
6774 
6775    The index sets may not have duplicate entries.
6776 
6777    When extracting submatrices from a parallel matrix, each processor can
6778    form a different submatrix by setting the rows and columns of its
6779    individual index sets according to the local submatrix desired.
6780 
6781    When finished using the submatrices, the user should destroy
6782    them with `MatDestroySubMatrices()`.
6783 
6784    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6785    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6786 
6787    This routine creates the matrices in submat; you should NOT create them before
6788    calling it. It also allocates the array of matrix pointers submat.
6789 
6790    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6791    request one row/column in a block, they must request all rows/columns that are in
6792    that block. For example, if the block size is 2 you cannot request just row 0 and
6793    column 0.
6794 
6795    Fortran Note:
6796    The Fortran interface is slightly different from that given below; it
6797    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.
6798 
6799    Level: advanced
6800 
6801 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6802 @*/
6803 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) {
6804   PetscInt  i;
6805   PetscBool eq;
6806 
6807   PetscFunctionBegin;
6808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6809   PetscValidType(mat, 1);
6810   if (n) {
6811     PetscValidPointer(irow, 3);
6812     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
6813     PetscValidPointer(icol, 4);
6814     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
6815   }
6816   PetscValidPointer(submat, 6);
6817   if (n && scall == MAT_REUSE_MATRIX) {
6818     PetscValidPointer(*submat, 6);
6819     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
6820   }
6821   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6822   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6823   MatCheckPreallocated(mat, 1);
6824   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
6825   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6826   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
6827   for (i = 0; i < n; i++) {
6828     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6829     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
6830     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
6831 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6832     if (mat->boundtocpu && mat->bindingpropagates) {
6833       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
6834       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
6835     }
6836 #endif
6837   }
6838   PetscFunctionReturn(0);
6839 }
6840 
6841 /*@C
6842    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
6843 
6844    Collective on mat
6845 
6846    Input Parameters:
6847 +  mat - the matrix
6848 .  n   - the number of submatrixes to be extracted
6849 .  irow, icol - index sets of rows and columns to extract
6850 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6851 
6852    Output Parameter:
6853 .  submat - the array of submatrices
6854 
6855    Level: advanced
6856 
6857    Note:
6858    This is used by `PCGASM`
6859 
6860 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6861 @*/
6862 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) {
6863   PetscInt  i;
6864   PetscBool eq;
6865 
6866   PetscFunctionBegin;
6867   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6868   PetscValidType(mat, 1);
6869   if (n) {
6870     PetscValidPointer(irow, 3);
6871     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
6872     PetscValidPointer(icol, 4);
6873     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
6874   }
6875   PetscValidPointer(submat, 6);
6876   if (n && scall == MAT_REUSE_MATRIX) {
6877     PetscValidPointer(*submat, 6);
6878     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
6879   }
6880   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6881   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6882   MatCheckPreallocated(mat, 1);
6883 
6884   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
6885   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6886   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
6887   for (i = 0; i < n; i++) {
6888     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
6889     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
6890   }
6891   PetscFunctionReturn(0);
6892 }
6893 
6894 /*@C
6895    MatDestroyMatrices - Destroys an array of matrices.
6896 
6897    Collective on mat
6898 
6899    Input Parameters:
6900 +  n - the number of local matrices
6901 -  mat - the matrices (note that this is a pointer to the array of matrices)
6902 
6903    Level: advanced
6904 
6905     Note:
6906     Frees not only the matrices, but also the array that contains the matrices
6907            In Fortran will not free the array.
6908 
6909 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6910 @*/
6911 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) {
6912   PetscInt i;
6913 
6914   PetscFunctionBegin;
6915   if (!*mat) PetscFunctionReturn(0);
6916   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
6917   PetscValidPointer(mat, 2);
6918 
6919   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
6920 
6921   /* memory is allocated even if n = 0 */
6922   PetscCall(PetscFree(*mat));
6923   PetscFunctionReturn(0);
6924 }
6925 
6926 /*@C
6927    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
6928 
6929    Collective on mat
6930 
6931    Input Parameters:
6932 +  n - the number of local matrices
6933 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6934                        sequence of MatCreateSubMatrices())
6935 
6936    Level: advanced
6937 
6938     Note:
6939     Frees not only the matrices, but also the array that contains the matrices
6940            In Fortran will not free the array.
6941 
6942 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6943 @*/
6944 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) {
6945   Mat mat0;
6946 
6947   PetscFunctionBegin;
6948   if (!*mat) PetscFunctionReturn(0);
6949   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
6950   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
6951   PetscValidPointer(mat, 2);
6952 
6953   mat0 = (*mat)[0];
6954   if (mat0 && mat0->ops->destroysubmatrices) {
6955     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
6956   } else {
6957     PetscCall(MatDestroyMatrices(n, mat));
6958   }
6959   PetscFunctionReturn(0);
6960 }
6961 
6962 /*@C
6963    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
6964 
6965    Collective on mat
6966 
6967    Input Parameters:
6968 .  mat - the matrix
6969 
6970    Output Parameter:
6971 .  matstruct - the sequential matrix with the nonzero structure of mat
6972 
6973   Level: developer
6974 
6975 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6976 @*/
6977 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) {
6978   PetscFunctionBegin;
6979   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6980   PetscValidPointer(matstruct, 2);
6981 
6982   PetscValidType(mat, 1);
6983   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6984   MatCheckPreallocated(mat, 1);
6985 
6986   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
6987   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
6988   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
6989   PetscFunctionReturn(0);
6990 }
6991 
6992 /*@C
6993    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
6994 
6995    Collective on mat
6996 
6997    Input Parameters:
6998 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
6999                        sequence of `MatGetSequentialNonzeroStructure()`)
7000 
7001    Level: advanced
7002 
7003     Note:
7004     Frees not only the matrices, but also the array that contains the matrices
7005 
7006 .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7007 @*/
7008 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) {
7009   PetscFunctionBegin;
7010   PetscValidPointer(mat, 1);
7011   PetscCall(MatDestroy(mat));
7012   PetscFunctionReturn(0);
7013 }
7014 
7015 /*@
7016    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7017    replaces the index sets by larger ones that represent submatrices with
7018    additional overlap.
7019 
7020    Collective on mat
7021 
7022    Input Parameters:
7023 +  mat - the matrix
7024 .  n   - the number of index sets
7025 .  is  - the array of index sets (these index sets will changed during the call)
7026 -  ov  - the additional overlap requested
7027 
7028    Options Database:
7029 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7030 
7031    Level: developer
7032 
7033    Developer Note:
7034    Any implementation must preserve block sizes. That is: if the row block size and the column block size of mat are equal to bs, then the output index sets must be compatible with bs.
7035 
7036 .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7037 @*/
7038 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) {
7039   PetscInt i, bs, cbs;
7040 
7041   PetscFunctionBegin;
7042   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7043   PetscValidType(mat, 1);
7044   PetscValidLogicalCollectiveInt(mat, n, 2);
7045   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7046   if (n) {
7047     PetscValidPointer(is, 3);
7048     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7049   }
7050   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7051   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7052   MatCheckPreallocated(mat, 1);
7053 
7054   if (!ov || !n) PetscFunctionReturn(0);
7055   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7056   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7057   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7058   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7059   if (bs == cbs) {
7060     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7061   }
7062   PetscFunctionReturn(0);
7063 }
7064 
7065 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7066 
7067 /*@
7068    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7069    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7070    additional overlap.
7071 
7072    Collective on mat
7073 
7074    Input Parameters:
7075 +  mat - the matrix
7076 .  n   - the number of index sets
7077 .  is  - the array of index sets (these index sets will changed during the call)
7078 -  ov  - the additional overlap requested
7079 
7080 `   Options Database:
7081 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7082 
7083    Level: developer
7084 
7085 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7086 @*/
7087 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) {
7088   PetscInt i;
7089 
7090   PetscFunctionBegin;
7091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7092   PetscValidType(mat, 1);
7093   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7094   if (n) {
7095     PetscValidPointer(is, 3);
7096     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7097   }
7098   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7099   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7100   MatCheckPreallocated(mat, 1);
7101   if (!ov) PetscFunctionReturn(0);
7102   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7103   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7104   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7105   PetscFunctionReturn(0);
7106 }
7107 
7108 /*@
7109    MatGetBlockSize - Returns the matrix block size.
7110 
7111    Not Collective
7112 
7113    Input Parameter:
7114 .  mat - the matrix
7115 
7116    Output Parameter:
7117 .  bs - block size
7118 
7119    Notes:
7120     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7121 
7122    If the block size has not been set yet this routine returns 1.
7123 
7124    Level: intermediate
7125 
7126 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7127 @*/
7128 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) {
7129   PetscFunctionBegin;
7130   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7131   PetscValidIntPointer(bs, 2);
7132   *bs = PetscAbs(mat->rmap->bs);
7133   PetscFunctionReturn(0);
7134 }
7135 
7136 /*@
7137    MatGetBlockSizes - Returns the matrix block row and column sizes.
7138 
7139    Not Collective
7140 
7141    Input Parameter:
7142 .  mat - the matrix
7143 
7144    Output Parameters:
7145 +  rbs - row block size
7146 -  cbs - column block size
7147 
7148    Notes:
7149     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7150     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7151 
7152    If a block size has not been set yet this routine returns 1.
7153 
7154    Level: intermediate
7155 
7156 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7157 @*/
7158 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) {
7159   PetscFunctionBegin;
7160   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7161   if (rbs) PetscValidIntPointer(rbs, 2);
7162   if (cbs) PetscValidIntPointer(cbs, 3);
7163   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7164   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7165   PetscFunctionReturn(0);
7166 }
7167 
7168 /*@
7169    MatSetBlockSize - Sets the matrix block size.
7170 
7171    Logically Collective on mat
7172 
7173    Input Parameters:
7174 +  mat - the matrix
7175 -  bs - block size
7176 
7177    Notes:
7178     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7179     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7180 
7181     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7182     is compatible with the matrix local sizes.
7183 
7184    Level: intermediate
7185 
7186 .seealso:  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7187 @*/
7188 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) {
7189   PetscFunctionBegin;
7190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7191   PetscValidLogicalCollectiveInt(mat, bs, 2);
7192   PetscCall(MatSetBlockSizes(mat, bs, bs));
7193   PetscFunctionReturn(0);
7194 }
7195 
7196 typedef struct {
7197   PetscInt         n;
7198   IS              *is;
7199   Mat             *mat;
7200   PetscObjectState nonzerostate;
7201   Mat              C;
7202 } EnvelopeData;
7203 
7204 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) {
7205   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7206   PetscCall(PetscFree(edata->is));
7207   PetscCall(PetscFree(edata));
7208   return 0;
7209 }
7210 
7211 /*
7212    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7213          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7214 
7215    Collective on mat
7216 
7217    Input Parameter:
7218 .  mat - the matrix
7219 
7220    Notes:
7221      There can be zeros within the blocks
7222 
7223      The blocks can overlap between processes, including laying on more than two processes
7224 
7225 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7226 */
7227 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) {
7228   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7229   PetscInt          *diag, *odiag, sc;
7230   VecScatter         scatter;
7231   PetscScalar       *seqv;
7232   const PetscScalar *parv;
7233   const PetscInt    *ia, *ja;
7234   PetscBool          set, flag, done;
7235   Mat                AA = mat, A;
7236   MPI_Comm           comm;
7237   PetscMPIInt        rank, size, tag;
7238   MPI_Status         status;
7239   PetscContainer     container;
7240   EnvelopeData      *edata;
7241   Vec                seq, par;
7242   IS                 isglobal;
7243 
7244   PetscFunctionBegin;
7245   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7246   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7247   if (!set || !flag) {
7248     /* TOO: only needs nonzero structure of transpose */
7249     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7250     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7251   }
7252   PetscCall(MatAIJGetLocalMat(AA, &A));
7253   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7254   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7255 
7256   PetscCall(MatGetLocalSize(mat, &n, NULL));
7257   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7258   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7259   PetscCallMPI(MPI_Comm_size(comm, &size));
7260   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7261 
7262   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7263 
7264   if (rank > 0) {
7265     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7266     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7267   }
7268   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7269   for (i = 0; i < n; i++) {
7270     env = PetscMax(env, ja[ia[i + 1] - 1]);
7271     II  = rstart + i;
7272     if (env == II) {
7273       starts[lblocks]  = tbs;
7274       sizes[lblocks++] = 1 + II - tbs;
7275       tbs              = 1 + II;
7276     }
7277   }
7278   if (rank < size - 1) {
7279     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7280     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7281   }
7282 
7283   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7284   if (!set || !flag) PetscCall(MatDestroy(&AA));
7285   PetscCall(MatDestroy(&A));
7286 
7287   PetscCall(PetscNew(&edata));
7288   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7289   edata->n = lblocks;
7290   /* create IS needed for extracting blocks from the original matrix */
7291   PetscCall(PetscMalloc1(lblocks, &edata->is));
7292   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7293 
7294   /* Create the resulting inverse matrix structure with preallocation information */
7295   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7296   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7297   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7298   PetscCall(MatSetType(edata->C, MATAIJ));
7299 
7300   /* Communicate the start and end of each row, from each block to the correct rank */
7301   /* TODO: Use PetscSF instead of VecScatter */
7302   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7303   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7304   PetscCall(VecGetArrayWrite(seq, &seqv));
7305   for (PetscInt i = 0; i < lblocks; i++) {
7306     for (PetscInt j = 0; j < sizes[i]; j++) {
7307       seqv[cnt]     = starts[i];
7308       seqv[cnt + 1] = starts[i] + sizes[i];
7309       cnt += 2;
7310     }
7311   }
7312   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7313   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7314   sc -= cnt;
7315   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7316   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7317   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7318   PetscCall(ISDestroy(&isglobal));
7319   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7320   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7321   PetscCall(VecScatterDestroy(&scatter));
7322   PetscCall(VecDestroy(&seq));
7323   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7324   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7325   PetscCall(VecGetArrayRead(par, &parv));
7326   cnt = 0;
7327   PetscCall(MatGetSize(mat, NULL, &n));
7328   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7329     PetscInt start, end, d = 0, od = 0;
7330 
7331     start = (PetscInt)PetscRealPart(parv[cnt]);
7332     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7333     cnt += 2;
7334 
7335     if (start < cstart) {
7336       od += cstart - start + n - cend;
7337       d += cend - cstart;
7338     } else if (start < cend) {
7339       od += n - cend;
7340       d += cend - start;
7341     } else od += n - start;
7342     if (end <= cstart) {
7343       od -= cstart - end + n - cend;
7344       d -= cend - cstart;
7345     } else if (end < cend) {
7346       od -= n - cend;
7347       d -= cend - end;
7348     } else od -= n - end;
7349 
7350     odiag[i] = od;
7351     diag[i]  = d;
7352   }
7353   PetscCall(VecRestoreArrayRead(par, &parv));
7354   PetscCall(VecDestroy(&par));
7355   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7356   PetscCall(PetscFree2(diag, odiag));
7357   PetscCall(PetscFree2(sizes, starts));
7358 
7359   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7360   PetscCall(PetscContainerSetPointer(container, edata));
7361   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7362   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7363   PetscCall(PetscObjectDereference((PetscObject)container));
7364   PetscFunctionReturn(0);
7365 }
7366 
7367 /*@
7368   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7369 
7370   Collective on A
7371 
7372   Input Parameters:
7373 . A - the matrix
7374 
7375   Output Parameters:
7376 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7377 
7378   Note:
7379      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7380 
7381   Level: advanced
7382 
7383 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7384 @*/
7385 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) {
7386   PetscContainer   container;
7387   EnvelopeData    *edata;
7388   PetscObjectState nonzerostate;
7389 
7390   PetscFunctionBegin;
7391   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7392   if (!container) {
7393     PetscCall(MatComputeVariableBlockEnvelope(A));
7394     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7395   }
7396   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7397   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7398   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7399   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7400 
7401   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7402   *C = edata->C;
7403 
7404   for (PetscInt i = 0; i < edata->n; i++) {
7405     Mat          D;
7406     PetscScalar *dvalues;
7407 
7408     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7409     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7410     PetscCall(MatSeqDenseInvert(D));
7411     PetscCall(MatDenseGetArray(D, &dvalues));
7412     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7413     PetscCall(MatDestroy(&D));
7414   }
7415   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7416   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7417   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7418   PetscFunctionReturn(0);
7419 }
7420 
7421 /*@
7422    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7423 
7424    Logically Collective on mat
7425 
7426    Input Parameters:
7427 +  mat - the matrix
7428 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7429 -  bsizes - the block sizes
7430 
7431    Notes:
7432     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7433 
7434     Each variable point-block set of degrees of freedom must live on a single MPI rank. That is a point block cannot straddle two MPI ranks.
7435 
7436    Level: intermediate
7437 
7438 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7439           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7440 @*/
7441 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) {
7442   PetscInt i, ncnt = 0, nlocal;
7443 
7444   PetscFunctionBegin;
7445   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7446   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7447   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7448   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7449   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);
7450   PetscCall(PetscFree(mat->bsizes));
7451   mat->nblocks = nblocks;
7452   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7453   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7454   PetscFunctionReturn(0);
7455 }
7456 
7457 /*@C
7458    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7459 
7460    Logically Collective on mat
7461 
7462    Input Parameter:
7463 .  mat - the matrix
7464 
7465    Output Parameters:
7466 +  nblocks - the number of blocks on this process
7467 -  bsizes - the block sizes
7468 
7469    Fortran Note:
7470    Currently not supported from Fortran
7471 
7472    Level: intermediate
7473 
7474 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7475 @*/
7476 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) {
7477   PetscFunctionBegin;
7478   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7479   *nblocks = mat->nblocks;
7480   *bsizes  = mat->bsizes;
7481   PetscFunctionReturn(0);
7482 }
7483 
7484 /*@
7485    MatSetBlockSizes - Sets the matrix block row and column sizes.
7486 
7487    Logically Collective on mat
7488 
7489    Input Parameters:
7490 +  mat - the matrix
7491 .  rbs - row block size
7492 -  cbs - column block size
7493 
7494    Notes:
7495     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7496     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7497     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7498 
7499     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7500     are compatible with the matrix local sizes.
7501 
7502     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7503 
7504    Level: intermediate
7505 
7506 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7507 @*/
7508 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) {
7509   PetscFunctionBegin;
7510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7511   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7512   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7513   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7514   if (mat->rmap->refcnt) {
7515     ISLocalToGlobalMapping l2g  = NULL;
7516     PetscLayout            nmap = NULL;
7517 
7518     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7519     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7520     PetscCall(PetscLayoutDestroy(&mat->rmap));
7521     mat->rmap          = nmap;
7522     mat->rmap->mapping = l2g;
7523   }
7524   if (mat->cmap->refcnt) {
7525     ISLocalToGlobalMapping l2g  = NULL;
7526     PetscLayout            nmap = NULL;
7527 
7528     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7529     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7530     PetscCall(PetscLayoutDestroy(&mat->cmap));
7531     mat->cmap          = nmap;
7532     mat->cmap->mapping = l2g;
7533   }
7534   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7535   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7536   PetscFunctionReturn(0);
7537 }
7538 
7539 /*@
7540    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7541 
7542    Logically Collective on mat
7543 
7544    Input Parameters:
7545 +  mat - the matrix
7546 .  fromRow - matrix from which to copy row block size
7547 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7548 
7549    Level: developer
7550 
7551 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7552 @*/
7553 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) {
7554   PetscFunctionBegin;
7555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7556   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7557   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7558   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7559   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7560   PetscFunctionReturn(0);
7561 }
7562 
7563 /*@
7564    MatResidual - Default routine to calculate the residual r = b - Ax
7565 
7566    Collective on mat
7567 
7568    Input Parameters:
7569 +  mat - the matrix
7570 .  b   - the right-hand-side
7571 -  x   - the approximate solution
7572 
7573    Output Parameter:
7574 .  r - location to store the residual
7575 
7576    Level: developer
7577 
7578 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7579 @*/
7580 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) {
7581   PetscFunctionBegin;
7582   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7583   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7584   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7585   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7586   PetscValidType(mat, 1);
7587   MatCheckPreallocated(mat, 1);
7588   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7589   if (!mat->ops->residual) {
7590     PetscCall(MatMult(mat, x, r));
7591     PetscCall(VecAYPX(r, -1.0, b));
7592   } else {
7593     PetscUseTypeMethod(mat, residual, b, x, r);
7594   }
7595   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7596   PetscFunctionReturn(0);
7597 }
7598 
7599 /*@C
7600     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7601 
7602    Collective on mat
7603 
7604     Input Parameters:
7605 +   mat - the matrix
7606 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7607 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7608 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7609                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7610                  always used.
7611 
7612     Output Parameters:
7613 +   n - number of local rows in the (possibly compressed) matrix
7614 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7615 .   ja - the column indices
7616 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7617            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7618 
7619     Level: developer
7620 
7621     Notes:
7622     You CANNOT change any of the ia[] or ja[] values.
7623 
7624     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7625 
7626     Fortran Notes:
7627     In Fortran use
7628 $
7629 $      PetscInt ia(1), ja(1)
7630 $      PetscOffset iia, jja
7631 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7632 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7633 
7634      or
7635 $
7636 $    PetscInt, pointer :: ia(:),ja(:)
7637 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7638 $    ! Access the ith and jth entries via ia(i) and ja(j)
7639 
7640 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7641 @*/
7642 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7643   PetscFunctionBegin;
7644   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7645   PetscValidType(mat, 1);
7646   if (n) PetscValidIntPointer(n, 5);
7647   if (ia) PetscValidPointer(ia, 6);
7648   if (ja) PetscValidPointer(ja, 7);
7649   if (done) PetscValidBoolPointer(done, 8);
7650   MatCheckPreallocated(mat, 1);
7651   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7652   else {
7653     if (done) *done = PETSC_TRUE;
7654     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7655     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7656     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7657   }
7658   PetscFunctionReturn(0);
7659 }
7660 
7661 /*@C
7662     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7663 
7664     Collective on mat
7665 
7666     Input Parameters:
7667 +   mat - the matrix
7668 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7669 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7670                 symmetrized
7671 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7672                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7673                  always used.
7674 .   n - number of columns in the (possibly compressed) matrix
7675 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7676 -   ja - the row indices
7677 
7678     Output Parameters:
7679 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7680 
7681     Level: developer
7682 
7683 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7684 @*/
7685 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7686   PetscFunctionBegin;
7687   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7688   PetscValidType(mat, 1);
7689   PetscValidIntPointer(n, 5);
7690   if (ia) PetscValidPointer(ia, 6);
7691   if (ja) PetscValidPointer(ja, 7);
7692   PetscValidBoolPointer(done, 8);
7693   MatCheckPreallocated(mat, 1);
7694   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7695   else {
7696     *done = PETSC_TRUE;
7697     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7698   }
7699   PetscFunctionReturn(0);
7700 }
7701 
7702 /*@C
7703     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7704 
7705     Collective on mat
7706 
7707     Input Parameters:
7708 +   mat - the matrix
7709 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7710 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7711 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7712                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7713                  always used.
7714 .   n - size of (possibly compressed) matrix
7715 .   ia - the row pointers
7716 -   ja - the column indices
7717 
7718     Output Parameters:
7719 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7720 
7721     Note:
7722     This routine zeros out n, ia, and ja. This is to prevent accidental
7723     us of the array after it has been restored. If you pass NULL, it will
7724     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7725 
7726     Level: developer
7727 
7728 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7729 @*/
7730 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7731   PetscFunctionBegin;
7732   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7733   PetscValidType(mat, 1);
7734   if (ia) PetscValidPointer(ia, 6);
7735   if (ja) PetscValidPointer(ja, 7);
7736   if (done) PetscValidBoolPointer(done, 8);
7737   MatCheckPreallocated(mat, 1);
7738 
7739   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7740   else {
7741     if (done) *done = PETSC_TRUE;
7742     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7743     if (n) *n = 0;
7744     if (ia) *ia = NULL;
7745     if (ja) *ja = NULL;
7746   }
7747   PetscFunctionReturn(0);
7748 }
7749 
7750 /*@C
7751     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7752 
7753     Collective on Mat
7754 
7755     Input Parameters:
7756 +   mat - the matrix
7757 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7758 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7759 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7760                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7761                  always used.
7762 
7763     Output Parameters:
7764 +   n - size of (possibly compressed) matrix
7765 .   ia - the column pointers
7766 .   ja - the row indices
7767 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7768 
7769     Level: developer
7770 
7771 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7772 @*/
7773 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7774   PetscFunctionBegin;
7775   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7776   PetscValidType(mat, 1);
7777   if (ia) PetscValidPointer(ia, 6);
7778   if (ja) PetscValidPointer(ja, 7);
7779   PetscValidBoolPointer(done, 8);
7780   MatCheckPreallocated(mat, 1);
7781 
7782   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7783   else {
7784     *done = PETSC_TRUE;
7785     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7786     if (n) *n = 0;
7787     if (ia) *ia = NULL;
7788     if (ja) *ja = NULL;
7789   }
7790   PetscFunctionReturn(0);
7791 }
7792 
7793 /*@C
7794     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
7795 
7796     Collective on mat
7797 
7798     Input Parameters:
7799 +   mat - the matrix
7800 .   ncolors - max color value
7801 .   n   - number of entries in colorarray
7802 -   colorarray - array indicating color for each column
7803 
7804     Output Parameters:
7805 .   iscoloring - coloring generated using colorarray information
7806 
7807     Level: developer
7808 
7809 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7810 @*/
7811 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) {
7812   PetscFunctionBegin;
7813   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7814   PetscValidType(mat, 1);
7815   PetscValidIntPointer(colorarray, 4);
7816   PetscValidPointer(iscoloring, 5);
7817   MatCheckPreallocated(mat, 1);
7818 
7819   if (!mat->ops->coloringpatch) {
7820     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
7821   } else {
7822     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7823   }
7824   PetscFunctionReturn(0);
7825 }
7826 
7827 /*@
7828    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7829 
7830    Logically Collective on mat
7831 
7832    Input Parameter:
7833 .  mat - the factored matrix to be reset
7834 
7835    Notes:
7836    This routine should be used only with factored matrices formed by in-place
7837    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7838    format).  This option can save memory, for example, when solving nonlinear
7839    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7840    ILU(0) preconditioner.
7841 
7842    Note that one can specify in-place ILU(0) factorization by calling
7843 .vb
7844      PCType(pc,PCILU);
7845      PCFactorSeUseInPlace(pc);
7846 .ve
7847    or by using the options -pc_type ilu -pc_factor_in_place
7848 
7849    In-place factorization ILU(0) can also be used as a local
7850    solver for the blocks within the block Jacobi or additive Schwarz
7851    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7852    for details on setting local solver options.
7853 
7854    Most users should employ the `KSP` interface for linear solvers
7855    instead of working directly with matrix algebra routines such as this.
7856    See, e.g., `KSPCreate()`.
7857 
7858    Level: developer
7859 
7860 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7861 @*/
7862 PetscErrorCode MatSetUnfactored(Mat mat) {
7863   PetscFunctionBegin;
7864   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7865   PetscValidType(mat, 1);
7866   MatCheckPreallocated(mat, 1);
7867   mat->factortype = MAT_FACTOR_NONE;
7868   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
7869   PetscUseTypeMethod(mat, setunfactored);
7870   PetscFunctionReturn(0);
7871 }
7872 
7873 /*MC
7874     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
7875 
7876     Synopsis:
7877     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7878 
7879     Not collective
7880 
7881     Input Parameter:
7882 .   x - matrix
7883 
7884     Output Parameters:
7885 +   xx_v - the Fortran pointer to the array
7886 -   ierr - error code
7887 
7888     Example of Usage:
7889 .vb
7890       PetscScalar, pointer xx_v(:,:)
7891       ....
7892       call MatDenseGetArrayF90(x,xx_v,ierr)
7893       a = xx_v(3)
7894       call MatDenseRestoreArrayF90(x,xx_v,ierr)
7895 .ve
7896 
7897     Level: advanced
7898 
7899 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
7900 
7901 M*/
7902 
7903 /*MC
7904     MatDenseRestoreArrayF90 - Restores a matrix array that has been
7905     accessed with `MatDenseGetArrayF90()`.
7906 
7907     Synopsis:
7908     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7909 
7910     Not collective
7911 
7912     Input Parameters:
7913 +   x - matrix
7914 -   xx_v - the Fortran90 pointer to the array
7915 
7916     Output Parameter:
7917 .   ierr - error code
7918 
7919     Example of Usage:
7920 .vb
7921        PetscScalar, pointer xx_v(:,:)
7922        ....
7923        call MatDenseGetArrayF90(x,xx_v,ierr)
7924        a = xx_v(3)
7925        call MatDenseRestoreArrayF90(x,xx_v,ierr)
7926 .ve
7927 
7928     Level: advanced
7929 
7930 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
7931 
7932 M*/
7933 
7934 /*MC
7935     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
7936 
7937     Synopsis:
7938     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7939 
7940     Not collective
7941 
7942     Input Parameter:
7943 .   x - matrix
7944 
7945     Output Parameters:
7946 +   xx_v - the Fortran pointer to the array
7947 -   ierr - error code
7948 
7949     Example of Usage:
7950 .vb
7951       PetscScalar, pointer xx_v(:)
7952       ....
7953       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7954       a = xx_v(3)
7955       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7956 .ve
7957 
7958     Level: advanced
7959 
7960 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
7961 
7962 M*/
7963 
7964 /*MC
7965     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
7966     accessed with `MatSeqAIJGetArrayF90()`.
7967 
7968     Synopsis:
7969     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7970 
7971     Not collective
7972 
7973     Input Parameters:
7974 +   x - matrix
7975 -   xx_v - the Fortran90 pointer to the array
7976 
7977     Output Parameter:
7978 .   ierr - error code
7979 
7980     Example of Usage:
7981 .vb
7982        PetscScalar, pointer xx_v(:)
7983        ....
7984        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7985        a = xx_v(3)
7986        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7987 .ve
7988 
7989     Level: advanced
7990 
7991 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
7992 
7993 M*/
7994 
7995 /*@
7996     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
7997                       as the original matrix.
7998 
7999     Collective on mat
8000 
8001     Input Parameters:
8002 +   mat - the original matrix
8003 .   isrow - parallel IS containing the rows this processor should obtain
8004 .   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.
8005 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8006 
8007     Output Parameter:
8008 .   newmat - the new submatrix, of the same type as the old
8009 
8010     Level: advanced
8011 
8012     Notes:
8013     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8014 
8015     Some matrix types place restrictions on the row and column indices, such
8016     as that they be sorted or that they be equal to each other.
8017 
8018     The index sets may not have duplicate entries.
8019 
8020       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8021    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8022    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8023    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8024    you are finished using it.
8025 
8026     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8027     the input matrix.
8028 
8029     If iscol is NULL then all columns are obtained (not supported in Fortran).
8030 
8031    Example usage:
8032    Consider the following 8x8 matrix with 34 non-zero values, that is
8033    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8034    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8035    as follows:
8036 
8037 .vb
8038             1  2  0  |  0  3  0  |  0  4
8039     Proc0   0  5  6  |  7  0  0  |  8  0
8040             9  0 10  | 11  0  0  | 12  0
8041     -------------------------------------
8042            13  0 14  | 15 16 17  |  0  0
8043     Proc1   0 18  0  | 19 20 21  |  0  0
8044             0  0  0  | 22 23  0  | 24  0
8045     -------------------------------------
8046     Proc2  25 26 27  |  0  0 28  | 29  0
8047            30  0  0  | 31 32 33  |  0 34
8048 .ve
8049 
8050     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8051 
8052 .vb
8053             2  0  |  0  3  0  |  0
8054     Proc0   5  6  |  7  0  0  |  8
8055     -------------------------------
8056     Proc1  18  0  | 19 20 21  |  0
8057     -------------------------------
8058     Proc2  26 27  |  0  0 28  | 29
8059             0  0  | 31 32 33  |  0
8060 .ve
8061 
8062 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8063 @*/
8064 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) {
8065   PetscMPIInt size;
8066   Mat        *local;
8067   IS          iscoltmp;
8068   PetscBool   flg;
8069 
8070   PetscFunctionBegin;
8071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8072   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8073   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8074   PetscValidPointer(newmat, 5);
8075   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8076   PetscValidType(mat, 1);
8077   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8078   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8079 
8080   MatCheckPreallocated(mat, 1);
8081   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8082 
8083   if (!iscol || isrow == iscol) {
8084     PetscBool   stride;
8085     PetscMPIInt grabentirematrix = 0, grab;
8086     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8087     if (stride) {
8088       PetscInt first, step, n, rstart, rend;
8089       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8090       if (step == 1) {
8091         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8092         if (rstart == first) {
8093           PetscCall(ISGetLocalSize(isrow, &n));
8094           if (n == rend - rstart) grabentirematrix = 1;
8095         }
8096       }
8097     }
8098     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8099     if (grab) {
8100       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8101       if (cll == MAT_INITIAL_MATRIX) {
8102         *newmat = mat;
8103         PetscCall(PetscObjectReference((PetscObject)mat));
8104       }
8105       PetscFunctionReturn(0);
8106     }
8107   }
8108 
8109   if (!iscol) {
8110     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8111   } else {
8112     iscoltmp = iscol;
8113   }
8114 
8115   /* if original matrix is on just one processor then use submatrix generated */
8116   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8117     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8118     goto setproperties;
8119   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8120     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8121     *newmat = *local;
8122     PetscCall(PetscFree(local));
8123     goto setproperties;
8124   } else if (!mat->ops->createsubmatrix) {
8125     /* Create a new matrix type that implements the operation using the full matrix */
8126     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8127     switch (cll) {
8128     case MAT_INITIAL_MATRIX: PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); break;
8129     case MAT_REUSE_MATRIX: PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); break;
8130     default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8131     }
8132     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8133     goto setproperties;
8134   }
8135 
8136   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8137   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8138   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8139 
8140 setproperties:
8141   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8142   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8143   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8144   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8145   PetscFunctionReturn(0);
8146 }
8147 
8148 /*@
8149    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8150 
8151    Not Collective
8152 
8153    Input Parameters:
8154 +  A - the matrix we wish to propagate options from
8155 -  B - the matrix we wish to propagate options to
8156 
8157    Level: beginner
8158 
8159    Note:
8160    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8161 
8162 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8163 @*/
8164 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) {
8165   PetscFunctionBegin;
8166   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8167   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8168   B->symmetry_eternal            = A->symmetry_eternal;
8169   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8170   B->symmetric                   = A->symmetric;
8171   B->structurally_symmetric      = A->structurally_symmetric;
8172   B->spd                         = A->spd;
8173   B->hermitian                   = A->hermitian;
8174   PetscFunctionReturn(0);
8175 }
8176 
8177 /*@
8178    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8179    used during the assembly process to store values that belong to
8180    other processors.
8181 
8182    Not Collective
8183 
8184    Input Parameters:
8185 +  mat   - the matrix
8186 .  size  - the initial size of the stash.
8187 -  bsize - the initial size of the block-stash(if used).
8188 
8189    Options Database Keys:
8190 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8191 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8192 
8193    Level: intermediate
8194 
8195    Notes:
8196      The block-stash is used for values set with `MatSetValuesBlocked()` while
8197      the stash is used for values set with `MatSetValues()`
8198 
8199      Run with the option -info and look for output of the form
8200      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8201      to determine the appropriate value, MM, to use for size and
8202      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8203      to determine the value, BMM to use for bsize
8204 
8205 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8206 @*/
8207 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) {
8208   PetscFunctionBegin;
8209   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8210   PetscValidType(mat, 1);
8211   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8212   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8213   PetscFunctionReturn(0);
8214 }
8215 
8216 /*@
8217    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8218      the matrix
8219 
8220    Neighbor-wise Collective on mat
8221 
8222    Input Parameters:
8223 +  mat   - the matrix
8224 .  x,y - the vectors
8225 -  w - where the result is stored
8226 
8227    Level: intermediate
8228 
8229    Notes:
8230     w may be the same vector as y.
8231 
8232     This allows one to use either the restriction or interpolation (its transpose)
8233     matrix to do the interpolation
8234 
8235 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8236 @*/
8237 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) {
8238   PetscInt M, N, Ny;
8239 
8240   PetscFunctionBegin;
8241   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8242   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8243   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8244   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8245   PetscCall(MatGetSize(A, &M, &N));
8246   PetscCall(VecGetSize(y, &Ny));
8247   if (M == Ny) {
8248     PetscCall(MatMultAdd(A, x, y, w));
8249   } else {
8250     PetscCall(MatMultTransposeAdd(A, x, y, w));
8251   }
8252   PetscFunctionReturn(0);
8253 }
8254 
8255 /*@
8256    MatInterpolate - y = A*x or A'*x depending on the shape of
8257      the matrix
8258 
8259    Neighbor-wise Collective on mat
8260 
8261    Input Parameters:
8262 +  mat   - the matrix
8263 -  x,y - the vectors
8264 
8265    Level: intermediate
8266 
8267    Note:
8268     This allows one to use either the restriction or interpolation (its transpose)
8269     matrix to do the interpolation
8270 
8271 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8272 @*/
8273 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) {
8274   PetscInt M, N, Ny;
8275 
8276   PetscFunctionBegin;
8277   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8278   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8279   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8280   PetscCall(MatGetSize(A, &M, &N));
8281   PetscCall(VecGetSize(y, &Ny));
8282   if (M == Ny) {
8283     PetscCall(MatMult(A, x, y));
8284   } else {
8285     PetscCall(MatMultTranspose(A, x, y));
8286   }
8287   PetscFunctionReturn(0);
8288 }
8289 
8290 /*@
8291    MatRestrict - y = A*x or A'*x
8292 
8293    Neighbor-wise Collective on Mat
8294 
8295    Input Parameters:
8296 +  mat   - the matrix
8297 -  x,y - the vectors
8298 
8299    Level: intermediate
8300 
8301    Note:
8302     This allows one to use either the restriction or interpolation (its transpose)
8303     matrix to do the restriction
8304 
8305 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8306 @*/
8307 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) {
8308   PetscInt M, N, Ny;
8309 
8310   PetscFunctionBegin;
8311   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8312   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8313   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8314   PetscCall(MatGetSize(A, &M, &N));
8315   PetscCall(VecGetSize(y, &Ny));
8316   if (M == Ny) {
8317     PetscCall(MatMult(A, x, y));
8318   } else {
8319     PetscCall(MatMultTranspose(A, x, y));
8320   }
8321   PetscFunctionReturn(0);
8322 }
8323 
8324 /*@
8325    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8326 
8327    Neighbor-wise Collective on Mat
8328 
8329    Input Parameters:
8330 +  mat   - the matrix
8331 -  w, x - the input dense matrices
8332 
8333    Output Parameters:
8334 .  y - the output dense matrix
8335 
8336    Level: intermediate
8337 
8338    Note:
8339     This allows one to use either the restriction or interpolation (its transpose)
8340     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8341     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8342 
8343 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8344 @*/
8345 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) {
8346   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8347   PetscBool trans = PETSC_TRUE;
8348   MatReuse  reuse = MAT_INITIAL_MATRIX;
8349 
8350   PetscFunctionBegin;
8351   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8352   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8353   PetscValidType(x, 2);
8354   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8355   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8356   PetscCall(MatGetSize(A, &M, &N));
8357   PetscCall(MatGetSize(x, &Mx, &Nx));
8358   if (N == Mx) trans = PETSC_FALSE;
8359   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);
8360   Mo = trans ? N : M;
8361   if (*y) {
8362     PetscCall(MatGetSize(*y, &My, &Ny));
8363     if (Mo == My && Nx == Ny) {
8364       reuse = MAT_REUSE_MATRIX;
8365     } else {
8366       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);
8367       PetscCall(MatDestroy(y));
8368     }
8369   }
8370 
8371   if (w && *y == w) { /* this is to minimize changes in PCMG */
8372     PetscBool flg;
8373 
8374     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8375     if (w) {
8376       PetscInt My, Ny, Mw, Nw;
8377 
8378       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8379       PetscCall(MatGetSize(*y, &My, &Ny));
8380       PetscCall(MatGetSize(w, &Mw, &Nw));
8381       if (!flg || My != Mw || Ny != Nw) w = NULL;
8382     }
8383     if (!w) {
8384       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8385       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8386       PetscCall(PetscLogObjectParent((PetscObject)*y, (PetscObject)w));
8387       PetscCall(PetscObjectDereference((PetscObject)w));
8388     } else {
8389       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8390     }
8391   }
8392   if (!trans) {
8393     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8394   } else {
8395     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8396   }
8397   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8398   PetscFunctionReturn(0);
8399 }
8400 
8401 /*@
8402    MatMatInterpolate - Y = A*X or A'*X
8403 
8404    Neighbor-wise Collective on Mat
8405 
8406    Input Parameters:
8407 +  mat   - the matrix
8408 -  x - the input dense matrix
8409 
8410    Output Parameters:
8411 .  y - the output dense matrix
8412 
8413    Level: intermediate
8414 
8415    Note:
8416     This allows one to use either the restriction or interpolation (its transpose)
8417     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8418     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8419 
8420 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8421 @*/
8422 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) {
8423   PetscFunctionBegin;
8424   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8425   PetscFunctionReturn(0);
8426 }
8427 
8428 /*@
8429    MatMatRestrict - Y = A*X or A'*X
8430 
8431    Neighbor-wise Collective on Mat
8432 
8433    Input Parameters:
8434 +  mat   - the matrix
8435 -  x - the input dense matrix
8436 
8437    Output Parameters:
8438 .  y - the output dense matrix
8439 
8440    Level: intermediate
8441 
8442    Note:
8443     This allows one to use either the restriction or interpolation (its transpose)
8444     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8445     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8446 
8447 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8448 @*/
8449 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) {
8450   PetscFunctionBegin;
8451   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8452   PetscFunctionReturn(0);
8453 }
8454 
8455 /*@
8456    MatGetNullSpace - retrieves the null space of a matrix.
8457 
8458    Logically Collective on mat
8459 
8460    Input Parameters:
8461 +  mat - the matrix
8462 -  nullsp - the null space object
8463 
8464    Level: developer
8465 
8466 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8467 @*/
8468 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) {
8469   PetscFunctionBegin;
8470   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8471   PetscValidPointer(nullsp, 2);
8472   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8473   PetscFunctionReturn(0);
8474 }
8475 
8476 /*@
8477    MatSetNullSpace - attaches a null space to a matrix.
8478 
8479    Logically Collective on mat
8480 
8481    Input Parameters:
8482 +  mat - the matrix
8483 -  nullsp - the null space object
8484 
8485    Level: advanced
8486 
8487    Notes:
8488       This null space is used by the `KSP` linear solvers to solve singular systems.
8489 
8490       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
8491 
8492       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
8493       to zero but the linear system will still be solved in a least squares sense.
8494 
8495       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8496    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).
8497    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
8498    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
8499    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).
8500    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8501 
8502     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8503     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8504     routine also automatically calls `MatSetTransposeNullSpace()`.
8505 
8506     The user should call `MatNullSpaceDestroy()`.
8507 
8508 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8509           `KSPSetPCSide()`
8510 @*/
8511 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) {
8512   PetscFunctionBegin;
8513   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8514   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8515   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8516   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8517   mat->nullsp = nullsp;
8518   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8519   PetscFunctionReturn(0);
8520 }
8521 
8522 /*@
8523    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8524 
8525    Logically Collective on mat
8526 
8527    Input Parameters:
8528 +  mat - the matrix
8529 -  nullsp - the null space object
8530 
8531    Level: developer
8532 
8533 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8534 @*/
8535 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) {
8536   PetscFunctionBegin;
8537   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8538   PetscValidType(mat, 1);
8539   PetscValidPointer(nullsp, 2);
8540   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8541   PetscFunctionReturn(0);
8542 }
8543 
8544 /*@
8545    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8546 
8547    Logically Collective on mat
8548 
8549    Input Parameters:
8550 +  mat - the matrix
8551 -  nullsp - the null space object
8552 
8553    Level: advanced
8554 
8555    Notes:
8556    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8557 
8558    See `MatSetNullSpace()`
8559 
8560 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8561 @*/
8562 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) {
8563   PetscFunctionBegin;
8564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8565   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8566   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8567   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8568   mat->transnullsp = nullsp;
8569   PetscFunctionReturn(0);
8570 }
8571 
8572 /*@
8573    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8574         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8575 
8576    Logically Collective on mat
8577 
8578    Input Parameters:
8579 +  mat - the matrix
8580 -  nullsp - the null space object
8581 
8582    Level: advanced
8583 
8584    Notes:
8585    Overwrites any previous near null space that may have been attached
8586 
8587    You can remove the null space by calling this routine with an nullsp of NULL
8588 
8589 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8590 @*/
8591 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) {
8592   PetscFunctionBegin;
8593   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8594   PetscValidType(mat, 1);
8595   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8596   MatCheckPreallocated(mat, 1);
8597   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8598   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8599   mat->nearnullsp = nullsp;
8600   PetscFunctionReturn(0);
8601 }
8602 
8603 /*@
8604    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8605 
8606    Not Collective
8607 
8608    Input Parameter:
8609 .  mat - the matrix
8610 
8611    Output Parameter:
8612 .  nullsp - the null space object, NULL if not set
8613 
8614    Level: advanced
8615 
8616 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8617 @*/
8618 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) {
8619   PetscFunctionBegin;
8620   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8621   PetscValidType(mat, 1);
8622   PetscValidPointer(nullsp, 2);
8623   MatCheckPreallocated(mat, 1);
8624   *nullsp = mat->nearnullsp;
8625   PetscFunctionReturn(0);
8626 }
8627 
8628 /*@C
8629    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8630 
8631    Collective on mat
8632 
8633    Input Parameters:
8634 +  mat - the matrix
8635 .  row - row/column permutation
8636 .  fill - expected fill factor >= 1.0
8637 -  level - level of fill, for ICC(k)
8638 
8639    Notes:
8640    Probably really in-place only when level of fill is zero, otherwise allocates
8641    new space to store factored matrix and deletes previous memory.
8642 
8643    Most users should employ the `KSP` interface for linear solvers
8644    instead of working directly with matrix algebra routines such as this.
8645    See, e.g., `KSPCreate()`.
8646 
8647    Level: developer
8648 
8649    Developer Note:
8650    The Fortran interface is not autogenerated as the f90
8651    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8652 
8653 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8654 @*/
8655 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) {
8656   PetscFunctionBegin;
8657   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8658   PetscValidType(mat, 1);
8659   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8660   PetscValidPointer(info, 3);
8661   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8662   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8663   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8664   MatCheckPreallocated(mat, 1);
8665   PetscUseTypeMethod(mat, iccfactor, row, info);
8666   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8667   PetscFunctionReturn(0);
8668 }
8669 
8670 /*@
8671    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8672          ghosted ones.
8673 
8674    Not Collective
8675 
8676    Input Parameters:
8677 +  mat - the matrix
8678 -  diag - the diagonal values, including ghost ones
8679 
8680    Level: developer
8681 
8682    Notes:
8683     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8684 
8685     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8686 
8687 .seealso: `MatDiagonalScale()`
8688 @*/
8689 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) {
8690   PetscMPIInt size;
8691 
8692   PetscFunctionBegin;
8693   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8694   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8695   PetscValidType(mat, 1);
8696 
8697   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8698   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8699   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8700   if (size == 1) {
8701     PetscInt n, m;
8702     PetscCall(VecGetSize(diag, &n));
8703     PetscCall(MatGetSize(mat, NULL, &m));
8704     if (m == n) {
8705       PetscCall(MatDiagonalScale(mat, NULL, diag));
8706     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8707   } else {
8708     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8709   }
8710   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
8711   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8712   PetscFunctionReturn(0);
8713 }
8714 
8715 /*@
8716    MatGetInertia - Gets the inertia from a factored matrix
8717 
8718    Collective on mat
8719 
8720    Input Parameter:
8721 .  mat - the matrix
8722 
8723    Output Parameters:
8724 +   nneg - number of negative eigenvalues
8725 .   nzero - number of zero eigenvalues
8726 -   npos - number of positive eigenvalues
8727 
8728    Level: advanced
8729 
8730    Note:
8731     Matrix must have been factored by `MatCholeskyFactor()`
8732 
8733 .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8734 @*/
8735 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) {
8736   PetscFunctionBegin;
8737   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8738   PetscValidType(mat, 1);
8739   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8740   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
8741   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8742   PetscFunctionReturn(0);
8743 }
8744 
8745 /* ----------------------------------------------------------------*/
8746 /*@C
8747    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8748 
8749    Neighbor-wise Collective on mat
8750 
8751    Input Parameters:
8752 +  mat - the factored matrix obtained with `MatGetFactor()`
8753 -  b - the right-hand-side vectors
8754 
8755    Output Parameter:
8756 .  x - the result vectors
8757 
8758    Note:
8759    The vectors b and x cannot be the same.  I.e., one cannot
8760    call `MatSolves`(A,x,x).
8761 
8762    Level: developer
8763 
8764 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8765 @*/
8766 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) {
8767   PetscFunctionBegin;
8768   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8769   PetscValidType(mat, 1);
8770   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
8771   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8772   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
8773 
8774   MatCheckPreallocated(mat, 1);
8775   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
8776   PetscUseTypeMethod(mat, solves, b, x);
8777   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
8778   PetscFunctionReturn(0);
8779 }
8780 
8781 /*@
8782    MatIsSymmetric - Test whether a matrix is symmetric
8783 
8784    Collective on mat
8785 
8786    Input Parameters:
8787 +  A - the matrix to test
8788 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8789 
8790    Output Parameters:
8791 .  flg - the result
8792 
8793    Notes:
8794     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8795 
8796     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
8797 
8798     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8799     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8800 
8801    Level: intermediate
8802 
8803 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8804           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8805 @*/
8806 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) {
8807   PetscFunctionBegin;
8808   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8809   PetscValidBoolPointer(flg, 3);
8810 
8811   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8812   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8813   else {
8814     if (!A->ops->issymmetric) {
8815       MatType mattype;
8816       PetscCall(MatGetType(A, &mattype));
8817       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8818     }
8819     PetscUseTypeMethod(A, issymmetric, tol, flg);
8820     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
8821   }
8822   PetscFunctionReturn(0);
8823 }
8824 
8825 /*@
8826    MatIsHermitian - Test whether a matrix is Hermitian
8827 
8828    Collective on Mat
8829 
8830    Input Parameters:
8831 +  A - the matrix to test
8832 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8833 
8834    Output Parameters:
8835 .  flg - the result
8836 
8837    Level: intermediate
8838 
8839    Notes:
8840     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8841 
8842     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
8843 
8844     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8845     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
8846 
8847 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8848           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8849 @*/
8850 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) {
8851   PetscFunctionBegin;
8852   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8853   PetscValidBoolPointer(flg, 3);
8854 
8855   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8856   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8857   else {
8858     if (!A->ops->ishermitian) {
8859       MatType mattype;
8860       PetscCall(MatGetType(A, &mattype));
8861       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8862     }
8863     PetscUseTypeMethod(A, ishermitian, tol, flg);
8864     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
8865   }
8866   PetscFunctionReturn(0);
8867 }
8868 
8869 /*@
8870    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
8871 
8872    Not Collective
8873 
8874    Input Parameter:
8875 .  A - the matrix to check
8876 
8877    Output Parameters:
8878 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8879 -  flg - the result (only valid if set is `PETSC_TRUE`)
8880 
8881    Level: advanced
8882 
8883    Notes:
8884    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8885    if you want it explicitly checked
8886 
8887     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8888     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8889 
8890 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8891 @*/
8892 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) {
8893   PetscFunctionBegin;
8894   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8895   PetscValidBoolPointer(set, 2);
8896   PetscValidBoolPointer(flg, 3);
8897   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8898     *set = PETSC_TRUE;
8899     *flg = PetscBool3ToBool(A->symmetric);
8900   } else {
8901     *set = PETSC_FALSE;
8902   }
8903   PetscFunctionReturn(0);
8904 }
8905 
8906 /*@
8907    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
8908 
8909    Not Collective
8910 
8911    Input Parameter:
8912 .  A - the matrix to check
8913 
8914    Output Parameters:
8915 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8916 -  flg - the result (only valid if set is `PETSC_TRUE`)
8917 
8918    Level: advanced
8919 
8920    Notes:
8921    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
8922 
8923    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
8924    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
8925 
8926 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8927 @*/
8928 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) {
8929   PetscFunctionBegin;
8930   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8931   PetscValidBoolPointer(set, 2);
8932   PetscValidBoolPointer(flg, 3);
8933   if (A->spd != PETSC_BOOL3_UNKNOWN) {
8934     *set = PETSC_TRUE;
8935     *flg = PetscBool3ToBool(A->spd);
8936   } else {
8937     *set = PETSC_FALSE;
8938   }
8939   PetscFunctionReturn(0);
8940 }
8941 
8942 /*@
8943    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
8944 
8945    Not Collective
8946 
8947    Input Parameter:
8948 .  A - the matrix to check
8949 
8950    Output Parameters:
8951 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
8952 -  flg - the result (only valid if set is `PETSC_TRUE`)
8953 
8954    Level: advanced
8955 
8956    Notes:
8957    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
8958    if you want it explicitly checked
8959 
8960    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8961    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8962 
8963 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
8964 @*/
8965 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) {
8966   PetscFunctionBegin;
8967   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8968   PetscValidBoolPointer(set, 2);
8969   PetscValidBoolPointer(flg, 3);
8970   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
8971     *set = PETSC_TRUE;
8972     *flg = PetscBool3ToBool(A->hermitian);
8973   } else {
8974     *set = PETSC_FALSE;
8975   }
8976   PetscFunctionReturn(0);
8977 }
8978 
8979 /*@
8980    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
8981 
8982    Collective on Mat
8983 
8984    Input Parameter:
8985 .  A - the matrix to test
8986 
8987    Output Parameters:
8988 .  flg - the result
8989 
8990    Notes:
8991    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
8992 
8993    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
8994    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8995 
8996    Level: intermediate
8997 
8998 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
8999 @*/
9000 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) {
9001   PetscFunctionBegin;
9002   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9003   PetscValidBoolPointer(flg, 2);
9004   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9005     *flg = PetscBool3ToBool(A->structurally_symmetric);
9006   } else {
9007     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9008     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9009   }
9010   PetscFunctionReturn(0);
9011 }
9012 
9013 /*@
9014    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9015 
9016    Not Collective
9017 
9018    Input Parameter:
9019 .  A - the matrix to check
9020 
9021    Output Parameters:
9022 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9023 -  flg - the result (only valid if set is PETSC_TRUE)
9024 
9025    Level: advanced
9026 
9027    Notes:
9028    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
9029    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9030 
9031    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9032 
9033 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9034 @*/
9035 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) {
9036   PetscFunctionBegin;
9037   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9038   PetscValidBoolPointer(set, 2);
9039   PetscValidBoolPointer(flg, 3);
9040   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9041     *set = PETSC_TRUE;
9042     *flg = PetscBool3ToBool(A->structurally_symmetric);
9043   } else {
9044     *set = PETSC_FALSE;
9045   }
9046   PetscFunctionReturn(0);
9047 }
9048 
9049 /*@
9050    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9051        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9052 
9053     Not collective
9054 
9055    Input Parameter:
9056 .   mat - the matrix
9057 
9058    Output Parameters:
9059 +   nstash   - the size of the stash
9060 .   reallocs - the number of additional mallocs incurred.
9061 .   bnstash   - the size of the block stash
9062 -   breallocs - the number of additional mallocs incurred.in the block stash
9063 
9064    Level: advanced
9065 
9066 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9067 @*/
9068 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) {
9069   PetscFunctionBegin;
9070   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9071   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9072   PetscFunctionReturn(0);
9073 }
9074 
9075 /*@C
9076    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9077    parallel layout, `PetscLayout` for rows and columns
9078 
9079    Collective on mat
9080 
9081    Input Parameter:
9082 .  mat - the matrix
9083 
9084    Output Parameters:
9085 +   right - (optional) vector that the matrix can be multiplied against
9086 -   left - (optional) vector that the matrix vector product can be stored in
9087 
9088    Notes:
9089     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()`.
9090 
9091     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9092 
9093   Level: advanced
9094 
9095 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9096 @*/
9097 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) {
9098   PetscFunctionBegin;
9099   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9100   PetscValidType(mat, 1);
9101   if (mat->ops->getvecs) {
9102     PetscUseTypeMethod(mat, getvecs, right, left);
9103   } else {
9104     PetscInt rbs, cbs;
9105     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9106     if (right) {
9107       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9108       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9109       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9110       PetscCall(VecSetBlockSize(*right, cbs));
9111       PetscCall(VecSetType(*right, mat->defaultvectype));
9112 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9113       if (mat->boundtocpu && mat->bindingpropagates) {
9114         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9115         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9116       }
9117 #endif
9118       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9119     }
9120     if (left) {
9121       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9122       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9123       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9124       PetscCall(VecSetBlockSize(*left, rbs));
9125       PetscCall(VecSetType(*left, mat->defaultvectype));
9126 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9127       if (mat->boundtocpu && mat->bindingpropagates) {
9128         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9129         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9130       }
9131 #endif
9132       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9133     }
9134   }
9135   PetscFunctionReturn(0);
9136 }
9137 
9138 /*@C
9139    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9140      with default values.
9141 
9142    Not Collective
9143 
9144    Input Parameters:
9145 .    info - the `MatFactorInfo` data structure
9146 
9147    Notes:
9148     The solvers are generally used through the `KSP` and `PC` objects, for example
9149           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9150 
9151     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9152 
9153    Level: developer
9154 
9155    Developer Note:
9156    The Fortran interface is not autogenerated as the f90
9157    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9158 
9159 .seealso: `MatGetFactor()`, `MatFactorInfo`
9160 @*/
9161 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) {
9162   PetscFunctionBegin;
9163   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9164   PetscFunctionReturn(0);
9165 }
9166 
9167 /*@
9168    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9169 
9170    Collective on mat
9171 
9172    Input Parameters:
9173 +  mat - the factored matrix
9174 -  is - the index set defining the Schur indices (0-based)
9175 
9176    Notes:
9177     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9178 
9179    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9180 
9181    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9182 
9183    Level: advanced
9184 
9185 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9186           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9187 
9188 @*/
9189 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) {
9190   PetscErrorCode (*f)(Mat, IS);
9191 
9192   PetscFunctionBegin;
9193   PetscValidType(mat, 1);
9194   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9195   PetscValidType(is, 2);
9196   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9197   PetscCheckSameComm(mat, 1, is, 2);
9198   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9199   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9200   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9201   PetscCall(MatDestroy(&mat->schur));
9202   PetscCall((*f)(mat, is));
9203   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9204   PetscFunctionReturn(0);
9205 }
9206 
9207 /*@
9208   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9209 
9210    Logically Collective on mat
9211 
9212    Input Parameters:
9213 +  F - the factored matrix obtained by calling `MatGetFactor()`
9214 .  S - location where to return the Schur complement, can be NULL
9215 -  status - the status of the Schur complement matrix, can be NULL
9216 
9217    Notes:
9218    You must call `MatFactorSetSchurIS()` before calling this routine.
9219 
9220    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9221 
9222    The routine provides a copy of the Schur matrix stored within the solver data structures.
9223    The caller must destroy the object when it is no longer needed.
9224    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9225 
9226    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)
9227 
9228    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9229 
9230    Developer Note:
9231     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9232    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9233 
9234    Level: advanced
9235 
9236 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9237 @*/
9238 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) {
9239   PetscFunctionBegin;
9240   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9241   if (S) PetscValidPointer(S, 2);
9242   if (status) PetscValidPointer(status, 3);
9243   if (S) {
9244     PetscErrorCode (*f)(Mat, Mat *);
9245 
9246     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9247     if (f) {
9248       PetscCall((*f)(F, S));
9249     } else {
9250       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9251     }
9252   }
9253   if (status) *status = F->schur_status;
9254   PetscFunctionReturn(0);
9255 }
9256 
9257 /*@
9258   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9259 
9260    Logically Collective on mat
9261 
9262    Input Parameters:
9263 +  F - the factored matrix obtained by calling `MatGetFactor()`
9264 .  *S - location where to return the Schur complement, can be NULL
9265 -  status - the status of the Schur complement matrix, can be NULL
9266 
9267    Notes:
9268    You must call `MatFactorSetSchurIS()` before calling this routine.
9269 
9270    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9271 
9272    The routine returns a the Schur Complement stored within the data strutures of the solver.
9273 
9274    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9275 
9276    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9277 
9278    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9279 
9280    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9281 
9282    Level: advanced
9283 
9284 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9285 @*/
9286 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) {
9287   PetscFunctionBegin;
9288   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9289   if (S) PetscValidPointer(S, 2);
9290   if (status) PetscValidPointer(status, 3);
9291   if (S) *S = F->schur;
9292   if (status) *status = F->schur_status;
9293   PetscFunctionReturn(0);
9294 }
9295 
9296 /*@
9297   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9298 
9299    Logically Collective on mat
9300 
9301    Input Parameters:
9302 +  F - the factored matrix obtained by calling `MatGetFactor()`
9303 .  *S - location where the Schur complement is stored
9304 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9305 
9306    Level: advanced
9307 
9308 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9309 @*/
9310 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) {
9311   PetscFunctionBegin;
9312   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9313   if (S) {
9314     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9315     *S = NULL;
9316   }
9317   F->schur_status = status;
9318   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9319   PetscFunctionReturn(0);
9320 }
9321 
9322 /*@
9323   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9324 
9325    Logically Collective on mat
9326 
9327    Input Parameters:
9328 +  F - the factored matrix obtained by calling `MatGetFactor()`
9329 .  rhs - location where the right hand side of the Schur complement system is stored
9330 -  sol - location where the solution of the Schur complement system has to be returned
9331 
9332    Notes:
9333    The sizes of the vectors should match the size of the Schur complement
9334 
9335    Must be called after `MatFactorSetSchurIS()`
9336 
9337    Level: advanced
9338 
9339 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9340 @*/
9341 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) {
9342   PetscFunctionBegin;
9343   PetscValidType(F, 1);
9344   PetscValidType(rhs, 2);
9345   PetscValidType(sol, 3);
9346   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9347   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9348   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9349   PetscCheckSameComm(F, 1, rhs, 2);
9350   PetscCheckSameComm(F, 1, sol, 3);
9351   PetscCall(MatFactorFactorizeSchurComplement(F));
9352   switch (F->schur_status) {
9353   case MAT_FACTOR_SCHUR_FACTORED: PetscCall(MatSolveTranspose(F->schur, rhs, sol)); break;
9354   case MAT_FACTOR_SCHUR_INVERTED: PetscCall(MatMultTranspose(F->schur, rhs, sol)); break;
9355   default: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9356   }
9357   PetscFunctionReturn(0);
9358 }
9359 
9360 /*@
9361   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9362 
9363    Logically Collective on mat
9364 
9365    Input Parameters:
9366 +  F - the factored matrix obtained by calling `MatGetFactor()`
9367 .  rhs - location where the right hand side of the Schur complement system is stored
9368 -  sol - location where the solution of the Schur complement system has to be returned
9369 
9370    Notes:
9371    The sizes of the vectors should match the size of the Schur complement
9372 
9373    Must be called after `MatFactorSetSchurIS()`
9374 
9375    Level: advanced
9376 
9377 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9378 @*/
9379 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) {
9380   PetscFunctionBegin;
9381   PetscValidType(F, 1);
9382   PetscValidType(rhs, 2);
9383   PetscValidType(sol, 3);
9384   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9385   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9386   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9387   PetscCheckSameComm(F, 1, rhs, 2);
9388   PetscCheckSameComm(F, 1, sol, 3);
9389   PetscCall(MatFactorFactorizeSchurComplement(F));
9390   switch (F->schur_status) {
9391   case MAT_FACTOR_SCHUR_FACTORED: PetscCall(MatSolve(F->schur, rhs, sol)); break;
9392   case MAT_FACTOR_SCHUR_INVERTED: PetscCall(MatMult(F->schur, rhs, sol)); break;
9393   default: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9394   }
9395   PetscFunctionReturn(0);
9396 }
9397 
9398 /*@
9399   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9400 
9401    Logically Collective on F
9402 
9403    Input Parameters:
9404 .  F - the factored matrix obtained by calling `MatGetFactor()`
9405 
9406    Notes:
9407     Must be called after `MatFactorSetSchurIS()`.
9408 
9409    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9410 
9411    Level: advanced
9412 
9413 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9414 @*/
9415 PetscErrorCode MatFactorInvertSchurComplement(Mat F) {
9416   PetscFunctionBegin;
9417   PetscValidType(F, 1);
9418   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9419   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9420   PetscCall(MatFactorFactorizeSchurComplement(F));
9421   PetscCall(MatFactorInvertSchurComplement_Private(F));
9422   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9423   PetscFunctionReturn(0);
9424 }
9425 
9426 /*@
9427   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9428 
9429    Logically Collective on mat
9430 
9431    Input Parameters:
9432 .  F - the factored matrix obtained by calling `MatGetFactor()`
9433 
9434    Note:
9435     Must be called after `MatFactorSetSchurIS()`
9436 
9437    Level: advanced
9438 
9439 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9440 @*/
9441 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) {
9442   PetscFunctionBegin;
9443   PetscValidType(F, 1);
9444   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9445   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9446   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9447   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9448   PetscFunctionReturn(0);
9449 }
9450 
9451 /*@
9452    MatPtAP - Creates the matrix product C = P^T * A * P
9453 
9454    Neighbor-wise Collective on A
9455 
9456    Input Parameters:
9457 +  A - the matrix
9458 .  P - the projection matrix
9459 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9460 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9461           if the result is a dense matrix this is irrelevant
9462 
9463    Output Parameters:
9464 .  C - the product matrix
9465 
9466    Notes:
9467    C will be created and must be destroyed by the user with `MatDestroy()`.
9468 
9469    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9470 
9471    Developer Note:
9472    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9473 
9474    Level: intermediate
9475 
9476 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9477 @*/
9478 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) {
9479   PetscFunctionBegin;
9480   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9481   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9482 
9483   if (scall == MAT_INITIAL_MATRIX) {
9484     PetscCall(MatProductCreate(A, P, NULL, C));
9485     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9486     PetscCall(MatProductSetAlgorithm(*C, "default"));
9487     PetscCall(MatProductSetFill(*C, fill));
9488 
9489     (*C)->product->api_user = PETSC_TRUE;
9490     PetscCall(MatProductSetFromOptions(*C));
9491     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);
9492     PetscCall(MatProductSymbolic(*C));
9493   } else { /* scall == MAT_REUSE_MATRIX */
9494     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9495   }
9496 
9497   PetscCall(MatProductNumeric(*C));
9498   (*C)->symmetric = A->symmetric;
9499   (*C)->spd       = A->spd;
9500   PetscFunctionReturn(0);
9501 }
9502 
9503 /*@
9504    MatRARt - Creates the matrix product C = R * A * R^T
9505 
9506    Neighbor-wise Collective on A
9507 
9508    Input Parameters:
9509 +  A - the matrix
9510 .  R - the projection matrix
9511 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9512 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9513           if the result is a dense matrix this is irrelevant
9514 
9515    Output Parameters:
9516 .  C - the product matrix
9517 
9518    Notes:
9519    C will be created and must be destroyed by the user with `MatDestroy()`.
9520 
9521    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9522 
9523    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9524    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9525    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9526    We recommend using MatPtAP().
9527 
9528    Level: intermediate
9529 
9530 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9531 @*/
9532 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) {
9533   PetscFunctionBegin;
9534   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9535   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9536 
9537   if (scall == MAT_INITIAL_MATRIX) {
9538     PetscCall(MatProductCreate(A, R, NULL, C));
9539     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9540     PetscCall(MatProductSetAlgorithm(*C, "default"));
9541     PetscCall(MatProductSetFill(*C, fill));
9542 
9543     (*C)->product->api_user = PETSC_TRUE;
9544     PetscCall(MatProductSetFromOptions(*C));
9545     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);
9546     PetscCall(MatProductSymbolic(*C));
9547   } else { /* scall == MAT_REUSE_MATRIX */
9548     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9549   }
9550 
9551   PetscCall(MatProductNumeric(*C));
9552   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9553   PetscFunctionReturn(0);
9554 }
9555 
9556 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) {
9557   PetscFunctionBegin;
9558   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9559 
9560   if (scall == MAT_INITIAL_MATRIX) {
9561     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9562     PetscCall(MatProductCreate(A, B, NULL, C));
9563     PetscCall(MatProductSetType(*C, ptype));
9564     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9565     PetscCall(MatProductSetFill(*C, fill));
9566 
9567     (*C)->product->api_user = PETSC_TRUE;
9568     PetscCall(MatProductSetFromOptions(*C));
9569     PetscCall(MatProductSymbolic(*C));
9570   } else { /* scall == MAT_REUSE_MATRIX */
9571     Mat_Product *product = (*C)->product;
9572     PetscBool    isdense;
9573 
9574     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9575     if (isdense && product && product->type != ptype) {
9576       PetscCall(MatProductClear(*C));
9577       product = NULL;
9578     }
9579     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9580     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9581       if (isdense) {
9582         PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9583         product           = (*C)->product;
9584         product->fill     = fill;
9585         product->api_user = PETSC_TRUE;
9586         product->clear    = PETSC_TRUE;
9587 
9588         PetscCall(MatProductSetType(*C, ptype));
9589         PetscCall(MatProductSetFromOptions(*C));
9590         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);
9591         PetscCall(MatProductSymbolic(*C));
9592       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9593     } else { /* user may change input matrices A or B when REUSE */
9594       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9595     }
9596   }
9597   PetscCall(MatProductNumeric(*C));
9598   PetscFunctionReturn(0);
9599 }
9600 
9601 /*@
9602    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9603 
9604    Neighbor-wise Collective on A
9605 
9606    Input Parameters:
9607 +  A - the left matrix
9608 .  B - the right matrix
9609 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9610 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9611           if the result is a dense matrix this is irrelevant
9612 
9613    Output Parameters:
9614 .  C - the product matrix
9615 
9616    Notes:
9617    Unless scall is `MAT_REUSE_MATRIX` C will be created.
9618 
9619    `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
9620    call to this function with `MAT_INITIAL_MATRIX`.
9621 
9622    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9623 
9624    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`,
9625    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9626 
9627    Example of Usage:
9628 .vb
9629      MatProductCreate(A,B,NULL,&C);
9630      MatProductSetType(C,MATPRODUCT_AB);
9631      MatProductSymbolic(C);
9632      MatProductNumeric(C); // compute C=A * B
9633      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9634      MatProductNumeric(C);
9635      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9636      MatProductNumeric(C);
9637 .ve
9638 
9639    Level: intermediate
9640 
9641 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9642 @*/
9643 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9644   PetscFunctionBegin;
9645   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
9646   PetscFunctionReturn(0);
9647 }
9648 
9649 /*@
9650    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9651 
9652    Neighbor-wise Collective on A
9653 
9654    Input Parameters:
9655 +  A - the left matrix
9656 .  B - the right matrix
9657 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9658 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9659 
9660    Output Parameters:
9661 .  C - the product matrix
9662 
9663    Notes:
9664    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9665 
9666    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9667 
9668    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9669    actually needed.
9670 
9671    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9672    and for pairs of `MATMPIDENSE` matrices.
9673 
9674    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9675 
9676    Options Database Keys:
9677 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9678               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9679               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9680 
9681    Level: intermediate
9682 
9683 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9684 @*/
9685 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9686   PetscFunctionBegin;
9687   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
9688   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9689   PetscFunctionReturn(0);
9690 }
9691 
9692 /*@
9693    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9694 
9695    Neighbor-wise Collective on A
9696 
9697    Input Parameters:
9698 +  A - the left matrix
9699 .  B - the right matrix
9700 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9701 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9702 
9703    Output Parameters:
9704 .  C - the product matrix
9705 
9706    Notes:
9707    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9708 
9709    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9710 
9711    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9712 
9713    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9714    actually needed.
9715 
9716    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9717    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
9718 
9719    Level: intermediate
9720 
9721 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9722 @*/
9723 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9724   PetscFunctionBegin;
9725   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
9726   PetscFunctionReturn(0);
9727 }
9728 
9729 /*@
9730    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
9731 
9732    Neighbor-wise Collective on A
9733 
9734    Input Parameters:
9735 +  A - the left matrix
9736 .  B - the middle matrix
9737 .  C - the right matrix
9738 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9739 -  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
9740           if the result is a dense matrix this is irrelevant
9741 
9742    Output Parameters:
9743 .  D - the product matrix
9744 
9745    Notes:
9746    Unless scall is `MAT_REUSE_MATRIX` D will be created.
9747 
9748    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9749 
9750    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
9751 
9752    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9753    actually needed.
9754 
9755    If you have many matrices with the same non-zero structure to multiply, you
9756    should use `MAT_REUSE_MATRIX` in all calls but the first
9757 
9758    Level: intermediate
9759 
9760 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9761 @*/
9762 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) {
9763   PetscFunctionBegin;
9764   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
9765   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9766 
9767   if (scall == MAT_INITIAL_MATRIX) {
9768     PetscCall(MatProductCreate(A, B, C, D));
9769     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
9770     PetscCall(MatProductSetAlgorithm(*D, "default"));
9771     PetscCall(MatProductSetFill(*D, fill));
9772 
9773     (*D)->product->api_user = PETSC_TRUE;
9774     PetscCall(MatProductSetFromOptions(*D));
9775     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,
9776                ((PetscObject)C)->type_name);
9777     PetscCall(MatProductSymbolic(*D));
9778   } else { /* user may change input matrices when REUSE */
9779     PetscCall(MatProductReplaceMats(A, B, C, *D));
9780   }
9781   PetscCall(MatProductNumeric(*D));
9782   PetscFunctionReturn(0);
9783 }
9784 
9785 /*@
9786    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9787 
9788    Collective on mat
9789 
9790    Input Parameters:
9791 +  mat - the matrix
9792 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9793 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9794 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9795 
9796    Output Parameter:
9797 .  matredundant - redundant matrix
9798 
9799    Notes:
9800    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9801    original matrix has not changed from that last call to MatCreateRedundantMatrix().
9802 
9803    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9804    calling it.
9805 
9806    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
9807 
9808    Level: advanced
9809 
9810 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9811 @*/
9812 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) {
9813   MPI_Comm       comm;
9814   PetscMPIInt    size;
9815   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9816   Mat_Redundant *redund     = NULL;
9817   PetscSubcomm   psubcomm   = NULL;
9818   MPI_Comm       subcomm_in = subcomm;
9819   Mat           *matseq;
9820   IS             isrow, iscol;
9821   PetscBool      newsubcomm = PETSC_FALSE;
9822 
9823   PetscFunctionBegin;
9824   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9825   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9826     PetscValidPointer(*matredundant, 5);
9827     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
9828   }
9829 
9830   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9831   if (size == 1 || nsubcomm == 1) {
9832     if (reuse == MAT_INITIAL_MATRIX) {
9833       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
9834     } else {
9835       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");
9836       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
9837     }
9838     PetscFunctionReturn(0);
9839   }
9840 
9841   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9842   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9843   MatCheckPreallocated(mat, 1);
9844 
9845   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
9846   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9847     /* create psubcomm, then get subcomm */
9848     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
9849     PetscCallMPI(MPI_Comm_size(comm, &size));
9850     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
9851 
9852     PetscCall(PetscSubcommCreate(comm, &psubcomm));
9853     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
9854     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
9855     PetscCall(PetscSubcommSetFromOptions(psubcomm));
9856     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
9857     newsubcomm = PETSC_TRUE;
9858     PetscCall(PetscSubcommDestroy(&psubcomm));
9859   }
9860 
9861   /* get isrow, iscol and a local sequential matrix matseq[0] */
9862   if (reuse == MAT_INITIAL_MATRIX) {
9863     mloc_sub = PETSC_DECIDE;
9864     nloc_sub = PETSC_DECIDE;
9865     if (bs < 1) {
9866       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
9867       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
9868     } else {
9869       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
9870       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
9871     }
9872     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
9873     rstart = rend - mloc_sub;
9874     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
9875     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
9876   } else { /* reuse == MAT_REUSE_MATRIX */
9877     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");
9878     /* retrieve subcomm */
9879     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
9880     redund = (*matredundant)->redundant;
9881     isrow  = redund->isrow;
9882     iscol  = redund->iscol;
9883     matseq = redund->matseq;
9884   }
9885   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
9886 
9887   /* get matredundant over subcomm */
9888   if (reuse == MAT_INITIAL_MATRIX) {
9889     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
9890 
9891     /* create a supporting struct and attach it to C for reuse */
9892     PetscCall(PetscNewLog(*matredundant, &redund));
9893     (*matredundant)->redundant = redund;
9894     redund->isrow              = isrow;
9895     redund->iscol              = iscol;
9896     redund->matseq             = matseq;
9897     if (newsubcomm) {
9898       redund->subcomm = subcomm;
9899     } else {
9900       redund->subcomm = MPI_COMM_NULL;
9901     }
9902   } else {
9903     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
9904   }
9905 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9906   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9907     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
9908     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
9909   }
9910 #endif
9911   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
9912   PetscFunctionReturn(0);
9913 }
9914 
9915 /*@C
9916    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
9917    a given `Mat`. Each submatrix can span multiple procs.
9918 
9919    Collective on mat
9920 
9921    Input Parameters:
9922 +  mat - the matrix
9923 .  subcomm - the subcommunicator obtained by MPI_Com_split(comm)
9924 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9925 
9926    Output Parameter:
9927 .  subMat - 'parallel submatrices each spans a given subcomm
9928 
9929   Notes:
9930   The submatrix partition across processors is dictated by 'subComm' a
9931   communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
9932   is not restriced to be grouped with consecutive original ranks.
9933 
9934   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
9935   map directly to the layout of the original matrix [wrt the local
9936   row,col partitioning]. So the original 'DiagonalMat' naturally maps
9937   into the 'DiagonalMat' of the subMat, hence it is used directly from
9938   the subMat. However the offDiagMat looses some columns - and this is
9939   reconstructed with `MatSetValues()`
9940 
9941   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
9942 
9943   Level: advanced
9944 
9945 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
9946 @*/
9947 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) {
9948   PetscMPIInt commsize, subCommSize;
9949 
9950   PetscFunctionBegin;
9951   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
9952   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
9953   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
9954 
9955   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");
9956   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
9957   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
9958   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
9959   PetscFunctionReturn(0);
9960 }
9961 
9962 /*@
9963    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
9964 
9965    Not Collective
9966 
9967    Input Parameters:
9968 +  mat - matrix to extract local submatrix from
9969 .  isrow - local row indices for submatrix
9970 -  iscol - local column indices for submatrix
9971 
9972    Output Parameter:
9973 .  submat - the submatrix
9974 
9975    Level: intermediate
9976 
9977    Notes:
9978    The submat should be returned with `MatRestoreLocalSubMatrix()`.
9979 
9980    Depending on the format of mat, the returned submat may not implement `MatMult()`.  Its communicator may be
9981    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
9982 
9983    The submat always implements `MatSetValuesLocal()`.  If isrow and iscol have the same block size, then
9984    `MatSetValuesBlockedLocal()` will also be implemented.
9985 
9986    The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
9987    Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
9988 
9989 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
9990 @*/
9991 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) {
9992   PetscFunctionBegin;
9993   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9994   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
9995   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
9996   PetscCheckSameComm(isrow, 2, iscol, 3);
9997   PetscValidPointer(submat, 4);
9998   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
9999 
10000   if (mat->ops->getlocalsubmatrix) {
10001     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10002   } else {
10003     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10004   }
10005   PetscFunctionReturn(0);
10006 }
10007 
10008 /*@
10009    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10010 
10011    Not Collective
10012 
10013    Input Parameters:
10014 +  mat - matrix to extract local submatrix from
10015 .  isrow - local row indices for submatrix
10016 .  iscol - local column indices for submatrix
10017 -  submat - the submatrix
10018 
10019    Level: intermediate
10020 
10021 .seealso: `MatGetLocalSubMatrix()`
10022 @*/
10023 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) {
10024   PetscFunctionBegin;
10025   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10026   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10027   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10028   PetscCheckSameComm(isrow, 2, iscol, 3);
10029   PetscValidPointer(submat, 4);
10030   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10031 
10032   if (mat->ops->restorelocalsubmatrix) {
10033     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10034   } else {
10035     PetscCall(MatDestroy(submat));
10036   }
10037   *submat = NULL;
10038   PetscFunctionReturn(0);
10039 }
10040 
10041 /* --------------------------------------------------------*/
10042 /*@
10043    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10044 
10045    Collective on mat
10046 
10047    Input Parameter:
10048 .  mat - the matrix
10049 
10050    Output Parameter:
10051 .  is - if any rows have zero diagonals this contains the list of them
10052 
10053    Level: developer
10054 
10055 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10056 @*/
10057 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) {
10058   PetscFunctionBegin;
10059   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10060   PetscValidType(mat, 1);
10061   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10062   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10063 
10064   if (!mat->ops->findzerodiagonals) {
10065     Vec                diag;
10066     const PetscScalar *a;
10067     PetscInt          *rows;
10068     PetscInt           rStart, rEnd, r, nrow = 0;
10069 
10070     PetscCall(MatCreateVecs(mat, &diag, NULL));
10071     PetscCall(MatGetDiagonal(mat, diag));
10072     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10073     PetscCall(VecGetArrayRead(diag, &a));
10074     for (r = 0; r < rEnd - rStart; ++r)
10075       if (a[r] == 0.0) ++nrow;
10076     PetscCall(PetscMalloc1(nrow, &rows));
10077     nrow = 0;
10078     for (r = 0; r < rEnd - rStart; ++r)
10079       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10080     PetscCall(VecRestoreArrayRead(diag, &a));
10081     PetscCall(VecDestroy(&diag));
10082     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10083   } else {
10084     PetscUseTypeMethod(mat, findzerodiagonals, is);
10085   }
10086   PetscFunctionReturn(0);
10087 }
10088 
10089 /*@
10090    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10091 
10092    Collective on mat
10093 
10094    Input Parameter:
10095 .  mat - the matrix
10096 
10097    Output Parameter:
10098 .  is - contains the list of rows with off block diagonal entries
10099 
10100    Level: developer
10101 
10102 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10103 @*/
10104 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) {
10105   PetscFunctionBegin;
10106   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10107   PetscValidType(mat, 1);
10108   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10109   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10110 
10111   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10112   PetscFunctionReturn(0);
10113 }
10114 
10115 /*@C
10116   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10117 
10118   Collective on mat
10119 
10120   Input Parameters:
10121 . mat - the matrix
10122 
10123   Output Parameters:
10124 . values - the block inverses in column major order (FORTRAN-like)
10125 
10126    Notes:
10127    The size of the blocks is determined by the block size of the matrix.
10128 
10129    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10130 
10131    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10132 
10133    Fortran Note:
10134      This routine is not available from Fortran.
10135 
10136   Level: advanced
10137 
10138 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10139 @*/
10140 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) {
10141   PetscFunctionBegin;
10142   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10143   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10144   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10145   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10146   PetscFunctionReturn(0);
10147 }
10148 
10149 /*@C
10150   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10151 
10152   Collective on mat
10153 
10154   Input Parameters:
10155 + mat - the matrix
10156 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10157 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10158 
10159   Output Parameters:
10160 . values - the block inverses in column major order (FORTRAN-like)
10161 
10162   Notes:
10163   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10164 
10165   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10166 
10167   Fortran Note:
10168   This routine is not available from Fortran.
10169 
10170   Level: advanced
10171 
10172 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10173 @*/
10174 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) {
10175   PetscFunctionBegin;
10176   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10177   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10178   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10179   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10180   PetscFunctionReturn(0);
10181 }
10182 
10183 /*@
10184   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10185 
10186   Collective on Mat
10187 
10188   Input Parameters:
10189 + A - the matrix
10190 - C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10191 
10192   Note:
10193   The blocksize of the matrix is used to determine the blocks on the diagonal of C
10194 
10195   Level: advanced
10196 
10197 .seealso: `MatInvertBlockDiagonal()`
10198 @*/
10199 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) {
10200   const PetscScalar *vals;
10201   PetscInt          *dnnz;
10202   PetscInt           m, rstart, rend, bs, i, j;
10203 
10204   PetscFunctionBegin;
10205   PetscCall(MatInvertBlockDiagonal(A, &vals));
10206   PetscCall(MatGetBlockSize(A, &bs));
10207   PetscCall(MatGetLocalSize(A, &m, NULL));
10208   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10209   PetscCall(PetscMalloc1(m / bs, &dnnz));
10210   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10211   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10212   PetscCall(PetscFree(dnnz));
10213   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10214   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10215   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10216   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10217   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10218   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10219   PetscFunctionReturn(0);
10220 }
10221 
10222 /*@C
10223     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10224     via `MatTransposeColoringCreate()`.
10225 
10226     Collective on c
10227 
10228     Input Parameter:
10229 .   c - coloring context
10230 
10231     Level: intermediate
10232 
10233 .seealso: `MatTransposeColoringCreate()`
10234 @*/
10235 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) {
10236   MatTransposeColoring matcolor = *c;
10237 
10238   PetscFunctionBegin;
10239   if (!matcolor) PetscFunctionReturn(0);
10240   if (--((PetscObject)matcolor)->refct > 0) {
10241     matcolor = NULL;
10242     PetscFunctionReturn(0);
10243   }
10244 
10245   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10246   PetscCall(PetscFree(matcolor->rows));
10247   PetscCall(PetscFree(matcolor->den2sp));
10248   PetscCall(PetscFree(matcolor->colorforcol));
10249   PetscCall(PetscFree(matcolor->columns));
10250   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10251   PetscCall(PetscHeaderDestroy(c));
10252   PetscFunctionReturn(0);
10253 }
10254 
10255 /*@C
10256     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10257     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10258     `MatTransposeColoring` to sparse B.
10259 
10260     Collective on coloring
10261 
10262     Input Parameters:
10263 +   B - sparse matrix B
10264 .   Btdense - symbolic dense matrix B^T
10265 -   coloring - coloring context created with `MatTransposeColoringCreate()`
10266 
10267     Output Parameter:
10268 .   Btdense - dense matrix B^T
10269 
10270     Level: developer
10271 
10272     Note:
10273     These are used internally for some implementations of `MatRARt()`
10274 
10275 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10276 
10277 @*/
10278 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) {
10279   PetscFunctionBegin;
10280   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10281   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10282   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10283 
10284   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10285   PetscFunctionReturn(0);
10286 }
10287 
10288 /*@C
10289     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10290     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10291     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10292     Csp from Cden.
10293 
10294     Collective on matcoloring
10295 
10296     Input Parameters:
10297 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10298 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10299 
10300     Output Parameter:
10301 .   Csp - sparse matrix
10302 
10303     Level: developer
10304 
10305     Note:
10306     These are used internally for some implementations of `MatRARt()`
10307 
10308 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10309 
10310 @*/
10311 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) {
10312   PetscFunctionBegin;
10313   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10314   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10315   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10316 
10317   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10318   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10319   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10320   PetscFunctionReturn(0);
10321 }
10322 
10323 /*@C
10324    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10325 
10326    Collective on mat
10327 
10328    Input Parameters:
10329 +  mat - the matrix product C
10330 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10331 
10332     Output Parameter:
10333 .   color - the new coloring context
10334 
10335     Level: intermediate
10336 
10337 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10338           `MatTransColoringApplyDenToSp()`
10339 @*/
10340 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) {
10341   MatTransposeColoring c;
10342   MPI_Comm             comm;
10343 
10344   PetscFunctionBegin;
10345   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10346   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10347   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10348 
10349   c->ctype = iscoloring->ctype;
10350   if (mat->ops->transposecoloringcreate) {
10351     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10352   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10353 
10354   *color = c;
10355   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10356   PetscFunctionReturn(0);
10357 }
10358 
10359 /*@
10360       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10361         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10362         same, otherwise it will be larger
10363 
10364      Not Collective
10365 
10366   Input Parameter:
10367 .    A  - the matrix
10368 
10369   Output Parameter:
10370 .    state - the current state
10371 
10372   Notes:
10373     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10374          different matrices
10375 
10376     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10377 
10378     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10379 
10380   Level: intermediate
10381 
10382 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10383 @*/
10384 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) {
10385   PetscFunctionBegin;
10386   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10387   *state = mat->nonzerostate;
10388   PetscFunctionReturn(0);
10389 }
10390 
10391 /*@
10392       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10393                  matrices from each processor
10394 
10395     Collective
10396 
10397    Input Parameters:
10398 +    comm - the communicators the parallel matrix will live on
10399 .    seqmat - the input sequential matrices
10400 .    n - number of local columns (or `PETSC_DECIDE`)
10401 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10402 
10403    Output Parameter:
10404 .    mpimat - the parallel matrix generated
10405 
10406     Level: developer
10407 
10408    Note:
10409     The number of columns of the matrix in EACH processor MUST be the same.
10410 
10411 .seealso: `Mat`
10412 @*/
10413 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) {
10414   PetscMPIInt size;
10415 
10416   PetscFunctionBegin;
10417   PetscCallMPI(MPI_Comm_size(comm, &size));
10418   if (size == 1) {
10419     if (reuse == MAT_INITIAL_MATRIX) {
10420       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10421     } else {
10422       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10423     }
10424     PetscFunctionReturn(0);
10425   }
10426 
10427   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");
10428 
10429   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10430   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10431   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10432   PetscFunctionReturn(0);
10433 }
10434 
10435 /*@
10436      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10437 
10438     Collective on A
10439 
10440    Input Parameters:
10441 +    A   - the matrix to create subdomains from
10442 -    N   - requested number of subdomains
10443 
10444    Output Parameters:
10445 +    n   - number of subdomains resulting on this rank
10446 -    iss - `IS` list with indices of subdomains on this rank
10447 
10448     Level: advanced
10449 
10450     Note:
10451     The number of subdomains must be smaller than the communicator size
10452 
10453 .seealso: `Mat`, `IS`
10454 @*/
10455 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) {
10456   MPI_Comm    comm, subcomm;
10457   PetscMPIInt size, rank, color;
10458   PetscInt    rstart, rend, k;
10459 
10460   PetscFunctionBegin;
10461   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10462   PetscCallMPI(MPI_Comm_size(comm, &size));
10463   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10464   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);
10465   *n    = 1;
10466   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10467   color = rank / k;
10468   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10469   PetscCall(PetscMalloc1(1, iss));
10470   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10471   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10472   PetscCallMPI(MPI_Comm_free(&subcomm));
10473   PetscFunctionReturn(0);
10474 }
10475 
10476 /*@
10477    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10478 
10479    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10480    If they are not the same, uses `MatMatMatMult()`.
10481 
10482    Once the coarse grid problem is constructed, correct for interpolation operators
10483    that are not of full rank, which can legitimately happen in the case of non-nested
10484    geometric multigrid.
10485 
10486    Input Parameters:
10487 +  restrct - restriction operator
10488 .  dA - fine grid matrix
10489 .  interpolate - interpolation operator
10490 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10491 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10492 
10493    Output Parameters:
10494 .  A - the Galerkin coarse matrix
10495 
10496    Options Database Key:
10497 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10498 
10499    Level: developer
10500 
10501 .seealso: `MatPtAP()`, `MatMatMatMult()`
10502 @*/
10503 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) {
10504   IS  zerorows;
10505   Vec diag;
10506 
10507   PetscFunctionBegin;
10508   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10509   /* Construct the coarse grid matrix */
10510   if (interpolate == restrct) {
10511     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10512   } else {
10513     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10514   }
10515 
10516   /* If the interpolation matrix is not of full rank, A will have zero rows.
10517      This can legitimately happen in the case of non-nested geometric multigrid.
10518      In that event, we set the rows of the matrix to the rows of the identity,
10519      ignoring the equations (as the RHS will also be zero). */
10520 
10521   PetscCall(MatFindZeroRows(*A, &zerorows));
10522 
10523   if (zerorows != NULL) { /* if there are any zero rows */
10524     PetscCall(MatCreateVecs(*A, &diag, NULL));
10525     PetscCall(MatGetDiagonal(*A, diag));
10526     PetscCall(VecISSet(diag, zerorows, 1.0));
10527     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10528     PetscCall(VecDestroy(&diag));
10529     PetscCall(ISDestroy(&zerorows));
10530   }
10531   PetscFunctionReturn(0);
10532 }
10533 
10534 /*@C
10535     MatSetOperation - Allows user to set a matrix operation for any matrix type
10536 
10537    Logically Collective on mat
10538 
10539     Input Parameters:
10540 +   mat - the matrix
10541 .   op - the name of the operation
10542 -   f - the function that provides the operation
10543 
10544    Level: developer
10545 
10546     Usage:
10547 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10548 $      PetscCall(MatCreateXXX(comm,...&A);
10549 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10550 
10551     Notes:
10552     See the file include/petscmat.h for a complete list of matrix
10553     operations, which all have the form MATOP_<OPERATION>, where
10554     <OPERATION> is the name (in all capital letters) of the
10555     user interface routine (e.g., MatMult() -> MATOP_MULT).
10556 
10557     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10558     sequence as the usual matrix interface routines, since they
10559     are intended to be accessed via the usual matrix interface
10560     routines, e.g.,
10561 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10562 
10563     In particular each function MUST return an error code of 0 on success and
10564     nonzero on failure.
10565 
10566     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10567 
10568 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10569 @*/
10570 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) {
10571   PetscFunctionBegin;
10572   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10573   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10574   (((void (**)(void))mat->ops)[op]) = f;
10575   PetscFunctionReturn(0);
10576 }
10577 
10578 /*@C
10579     MatGetOperation - Gets a matrix operation for any matrix type.
10580 
10581     Not Collective
10582 
10583     Input Parameters:
10584 +   mat - the matrix
10585 -   op - the name of the operation
10586 
10587     Output Parameter:
10588 .   f - the function that provides the operation
10589 
10590     Level: developer
10591 
10592     Usage:
10593 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10594 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10595 
10596     Notes:
10597     See the file include/petscmat.h for a complete list of matrix
10598     operations, which all have the form MATOP_<OPERATION>, where
10599     <OPERATION> is the name (in all capital letters) of the
10600     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10601 
10602     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10603 
10604 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10605 @*/
10606 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) {
10607   PetscFunctionBegin;
10608   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10609   *f = (((void (**)(void))mat->ops)[op]);
10610   PetscFunctionReturn(0);
10611 }
10612 
10613 /*@
10614     MatHasOperation - Determines whether the given matrix supports the particular operation.
10615 
10616    Not Collective
10617 
10618    Input Parameters:
10619 +  mat - the matrix
10620 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
10621 
10622    Output Parameter:
10623 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
10624 
10625    Level: advanced
10626 
10627    Note:
10628    See the file include/petscmat.h for a complete list of matrix
10629    operations, which all have the form MATOP_<OPERATION>, where
10630    <OPERATION> is the name (in all capital letters) of the
10631    user-level routine.  E.g., `MatNorm()` -> `MATOP_NORM`.
10632 
10633 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10634 @*/
10635 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) {
10636   PetscFunctionBegin;
10637   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10638   PetscValidBoolPointer(has, 3);
10639   if (mat->ops->hasoperation) {
10640     PetscUseTypeMethod(mat, hasoperation, op, has);
10641   } else {
10642     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10643     else {
10644       *has = PETSC_FALSE;
10645       if (op == MATOP_CREATE_SUBMATRIX) {
10646         PetscMPIInt size;
10647 
10648         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10649         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
10650       }
10651     }
10652   }
10653   PetscFunctionReturn(0);
10654 }
10655 
10656 /*@
10657     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10658 
10659    Collective on mat
10660 
10661    Input Parameters:
10662 .  mat - the matrix
10663 
10664    Output Parameter:
10665 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
10666 
10667    Level: beginner
10668 
10669 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10670 @*/
10671 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) {
10672   PetscFunctionBegin;
10673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10674   PetscValidType(mat, 1);
10675   PetscValidBoolPointer(cong, 2);
10676   if (!mat->rmap || !mat->cmap) {
10677     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10678     PetscFunctionReturn(0);
10679   }
10680   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10681     PetscCall(PetscLayoutSetUp(mat->rmap));
10682     PetscCall(PetscLayoutSetUp(mat->cmap));
10683     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
10684     if (*cong) mat->congruentlayouts = 1;
10685     else mat->congruentlayouts = 0;
10686   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10687   PetscFunctionReturn(0);
10688 }
10689 
10690 PetscErrorCode MatSetInf(Mat A) {
10691   PetscFunctionBegin;
10692   PetscUseTypeMethod(A, setinf);
10693   PetscFunctionReturn(0);
10694 }
10695 
10696 /*C
10697    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
10698 
10699    Collective on mat
10700 
10701    Input Parameters:
10702 +  A - the matrix
10703 -  sym - `PETSC_TRUE` indicates that the graph will be symmetrized
10704 .  scale - `PETSC_TRUE` indicates that the graph will be scaled with the diagonal
10705 
10706    Output Parameter:
10707 .  graph - the resulting graph
10708 
10709    Level: advanced
10710 
10711 .seealso: `MatCreate()`, `MatFilter()`
10712 */
10713 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, Mat *graph) {
10714   PetscFunctionBegin;
10715   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
10716   PetscValidType(A, 1);
10717   PetscValidPointer(graph, 3);
10718   PetscUseTypeMethod(A, creategraph, sym, scale, graph);
10719   PetscFunctionReturn(0);
10720 }
10721 
10722 /*C
10723    MatFilter - filters a matrices values with an absolut value equal to or below a give threshold
10724 
10725    Collective on mat
10726 
10727    Input Parameter:
10728 .  value - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries <= value
10729 
10730    Input/Output Parameter:
10731 .  A - the `Mat` to filter in place
10732 
10733    Level: developer
10734 
10735    Note:
10736    This is called before graph coarsers are called in `PCGAMG`
10737 
10738 .seealso: `MatCreate()`, `MatCreateGraph()`
10739 */
10740 PETSC_EXTERN PetscErrorCode MatFilter(Mat G, PetscReal value, Mat *F) {
10741   PetscFunctionBegin;
10742   PetscValidHeaderSpecific(G, MAT_CLASSID, 1);
10743   PetscValidType(G, 1);
10744   PetscValidPointer(F, 3);
10745   if (value >= 0.0) PetscCall((G->ops->filter)(G, value, F));
10746   PetscFunctionReturn(0);
10747 }
10748