xref: /petsc/src/mat/interface/matrix.c (revision 38f6737523616bfeabdd577adb30ea0990bf5fe7)
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 random number context, 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: `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(PetscRandomSetFromOptions(randObj));
86     rctx = randObj;
87   }
88   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
89   PetscUseTypeMethod(x, setrandom, rctx);
90   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
91 
92   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
93   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
94   PetscCall(PetscRandomDestroy(&randObj));
95   PetscFunctionReturn(0);
96 }
97 
98 /*@
99    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
100 
101    Logically Collective on Mat
102 
103    Input Parameter:
104 .  mat - the factored matrix
105 
106    Output Parameters:
107 +  pivot - the pivot value computed
108 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
109          the share the matrix
110 
111    Level: advanced
112 
113    Notes:
114     This routine does not work for factorizations done with external packages.
115 
116     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
117 
118     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
119 
120 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`
121 @*/
122 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) {
123   PetscFunctionBegin;
124   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
125   PetscValidRealPointer(pivot, 2);
126   PetscValidIntPointer(row, 3);
127   *pivot = mat->factorerror_zeropivot_value;
128   *row   = mat->factorerror_zeropivot_row;
129   PetscFunctionReturn(0);
130 }
131 
132 /*@
133    MatFactorGetError - gets the error code from a factorization
134 
135    Logically Collective on Mat
136 
137    Input Parameters:
138 .  mat - the factored matrix
139 
140    Output Parameter:
141 .  err  - the error code
142 
143    Level: advanced
144 
145    Notes:
146     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
147 
148 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
149           `MatErrorCode`
150 @*/
151 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) {
152   PetscFunctionBegin;
153   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
154   PetscValidPointer(err, 2);
155   *err = mat->factorerrortype;
156   PetscFunctionReturn(0);
157 }
158 
159 /*@
160    MatFactorClearError - clears the error code in a factorization
161 
162    Logically Collective on Mat
163 
164    Input Parameter:
165 .  mat - the factored matrix
166 
167    Level: developer
168 
169    Notes:
170     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
171 
172 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
173           `MatGetErrorCode()`, `MatErrorCode`
174 @*/
175 PetscErrorCode MatFactorClearError(Mat mat) {
176   PetscFunctionBegin;
177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
178   mat->factorerrortype             = MAT_FACTOR_NOERROR;
179   mat->factorerror_zeropivot_value = 0.0;
180   mat->factorerror_zeropivot_row   = 0;
181   PetscFunctionReturn(0);
182 }
183 
184 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) {
185   Vec                r, l;
186   const PetscScalar *al;
187   PetscInt           i, nz, gnz, N, n;
188 
189   PetscFunctionBegin;
190   PetscCall(MatCreateVecs(mat, &r, &l));
191   if (!cols) { /* nonzero rows */
192     PetscCall(MatGetSize(mat, &N, NULL));
193     PetscCall(MatGetLocalSize(mat, &n, NULL));
194     PetscCall(VecSet(l, 0.0));
195     PetscCall(VecSetRandom(r, NULL));
196     PetscCall(MatMult(mat, r, l));
197     PetscCall(VecGetArrayRead(l, &al));
198   } else { /* nonzero columns */
199     PetscCall(MatGetSize(mat, NULL, &N));
200     PetscCall(MatGetLocalSize(mat, NULL, &n));
201     PetscCall(VecSet(r, 0.0));
202     PetscCall(VecSetRandom(l, NULL));
203     PetscCall(MatMultTranspose(mat, l, r));
204     PetscCall(VecGetArrayRead(r, &al));
205   }
206   if (tol <= 0.0) {
207     for (i = 0, nz = 0; i < n; i++)
208       if (al[i] != 0.0) nz++;
209   } else {
210     for (i = 0, nz = 0; i < n; i++)
211       if (PetscAbsScalar(al[i]) > tol) nz++;
212   }
213   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
214   if (gnz != N) {
215     PetscInt *nzr;
216     PetscCall(PetscMalloc1(nz, &nzr));
217     if (nz) {
218       if (tol < 0) {
219         for (i = 0, nz = 0; i < n; i++)
220           if (al[i] != 0.0) nzr[nz++] = i;
221       } else {
222         for (i = 0, nz = 0; i < n; i++)
223           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
224       }
225     }
226     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
227   } else *nonzero = NULL;
228   if (!cols) { /* nonzero rows */
229     PetscCall(VecRestoreArrayRead(l, &al));
230   } else {
231     PetscCall(VecRestoreArrayRead(r, &al));
232   }
233   PetscCall(VecDestroy(&l));
234   PetscCall(VecDestroy(&r));
235   PetscFunctionReturn(0);
236 }
237 
238 /*@
239       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
240 
241   Input Parameter:
242 .    A  - the matrix
243 
244   Output Parameter:
245 .    keptrows - the rows that are not completely zero
246 
247   Notes:
248     keptrows is set to NULL if all rows are nonzero.
249 
250   Level: intermediate
251 
252  @*/
253 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) {
254   PetscFunctionBegin;
255   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
256   PetscValidType(mat, 1);
257   PetscValidPointer(keptrows, 2);
258   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
259   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
260   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
261   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
262   PetscFunctionReturn(0);
263 }
264 
265 /*@
266       MatFindZeroRows - Locate all rows that are completely zero in the matrix
267 
268   Input Parameter:
269 .    A  - the matrix
270 
271   Output Parameter:
272 .    zerorows - the rows that are completely zero
273 
274   Notes:
275     zerorows is set to NULL if no rows are zero.
276 
277   Level: intermediate
278 
279  @*/
280 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) {
281   IS       keptrows;
282   PetscInt m, n;
283 
284   PetscFunctionBegin;
285   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
286   PetscValidType(mat, 1);
287   PetscValidPointer(zerorows, 2);
288   PetscCall(MatFindNonzeroRows(mat, &keptrows));
289   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
290      In keeping with this convention, we set zerorows to NULL if there are no zero
291      rows. */
292   if (keptrows == NULL) {
293     *zerorows = NULL;
294   } else {
295     PetscCall(MatGetOwnershipRange(mat, &m, &n));
296     PetscCall(ISComplement(keptrows, m, n, zerorows));
297     PetscCall(ISDestroy(&keptrows));
298   }
299   PetscFunctionReturn(0);
300 }
301 
302 /*@
303    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
304 
305    Not Collective
306 
307    Input Parameters:
308 .   A - the matrix
309 
310    Output Parameters:
311 .   a - the diagonal part (which is a SEQUENTIAL matrix)
312 
313    Notes:
314    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
315 
316    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.
317 
318    Level: advanced
319 
320 .seelaso: `MatCreateAIJ()`
321 @*/
322 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) {
323   PetscFunctionBegin;
324   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
325   PetscValidType(A, 1);
326   PetscValidPointer(a, 2);
327   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
328   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
329   else {
330     PetscMPIInt size;
331 
332     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
333     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
334     *a = A;
335   }
336   PetscFunctionReturn(0);
337 }
338 
339 /*@
340    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
341 
342    Collective on Mat
343 
344    Input Parameters:
345 .  mat - the matrix
346 
347    Output Parameter:
348 .   trace - the sum of the diagonal entries
349 
350    Level: advanced
351 
352 @*/
353 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) {
354   Vec diag;
355 
356   PetscFunctionBegin;
357   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
358   PetscValidScalarPointer(trace, 2);
359   PetscCall(MatCreateVecs(mat, &diag, NULL));
360   PetscCall(MatGetDiagonal(mat, diag));
361   PetscCall(VecSum(diag, trace));
362   PetscCall(VecDestroy(&diag));
363   PetscFunctionReturn(0);
364 }
365 
366 /*@
367    MatRealPart - Zeros out the imaginary part of the matrix
368 
369    Logically Collective on Mat
370 
371    Input Parameters:
372 .  mat - the matrix
373 
374    Level: advanced
375 
376 .seealso: `MatImaginaryPart()`
377 @*/
378 PetscErrorCode MatRealPart(Mat mat) {
379   PetscFunctionBegin;
380   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
381   PetscValidType(mat, 1);
382   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
383   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
384   MatCheckPreallocated(mat, 1);
385   PetscUseTypeMethod(mat, realpart);
386   PetscFunctionReturn(0);
387 }
388 
389 /*@C
390    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
391 
392    Collective on Mat
393 
394    Input Parameter:
395 .  mat - the matrix
396 
397    Output Parameters:
398 +   nghosts - number of ghosts (note for BAIJ matrices there is one ghost for each block)
399 -   ghosts - the global indices of the ghost points
400 
401    Notes:
402     the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
403 
404    Level: advanced
405 
406 @*/
407 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) {
408   PetscFunctionBegin;
409   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
410   PetscValidType(mat, 1);
411   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
412   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
413   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
414   else {
415     if (nghosts) *nghosts = 0;
416     if (ghosts) *ghosts = NULL;
417   }
418   PetscFunctionReturn(0);
419 }
420 
421 /*@
422    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
423 
424    Logically Collective on Mat
425 
426    Input Parameters:
427 .  mat - the matrix
428 
429    Level: advanced
430 
431 .seealso: `MatRealPart()`
432 @*/
433 PetscErrorCode MatImaginaryPart(Mat mat) {
434   PetscFunctionBegin;
435   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
436   PetscValidType(mat, 1);
437   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
438   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
439   MatCheckPreallocated(mat, 1);
440   PetscUseTypeMethod(mat, imaginarypart);
441   PetscFunctionReturn(0);
442 }
443 
444 /*@
445    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for BAIJ matrices)
446 
447    Not Collective
448 
449    Input Parameter:
450 .  mat - the matrix
451 
452    Output Parameters:
453 +  missing - is any diagonal missing
454 -  dd - first diagonal entry that is missing (optional) on this process
455 
456    Level: advanced
457 
458 .seealso: `MatRealPart()`
459 @*/
460 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) {
461   PetscFunctionBegin;
462   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
463   PetscValidType(mat, 1);
464   PetscValidBoolPointer(missing, 2);
465   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
466   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
467   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
468   PetscFunctionReturn(0);
469 }
470 
471 /*@C
472    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
473    for each row that you get to ensure that your application does
474    not bleed memory.
475 
476    Not Collective
477 
478    Input Parameters:
479 +  mat - the matrix
480 -  row - the row to get
481 
482    Output Parameters:
483 +  ncols -  if not NULL, the number of nonzeros in the row
484 .  cols - if not NULL, the column numbers
485 -  vals - if not NULL, the values
486 
487    Notes:
488    This routine is provided for people who need to have direct access
489    to the structure of a matrix.  We hope that we provide enough
490    high-level matrix routines that few users will need it.
491 
492    `MatGetRow()` always returns 0-based column indices, regardless of
493    whether the internal representation is 0-based (default) or 1-based.
494 
495    For better efficiency, set cols and/or vals to NULL if you do
496    not wish to extract these quantities.
497 
498    The user can only examine the values extracted with `MatGetRow()`;
499    the values cannot be altered.  To change the matrix entries, one
500    must use `MatSetValues()`.
501 
502    You can only have one call to `MatGetRow()` outstanding for a particular
503    matrix at a time, per processor. `MatGetRow()` can only obtain rows
504    associated with the given processor, it cannot get rows from the
505    other processors; for that we suggest using `MatCreateSubMatrices()`, then
506    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
507    is in the global number of rows.
508 
509    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
510 
511    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
512 
513    Fortran Notes:
514    The calling sequence from Fortran is
515 .vb
516    MatGetRow(matrix,row,ncols,cols,values,ierr)
517          Mat     matrix (input)
518          integer row    (input)
519          integer ncols  (output)
520          integer cols(maxcols) (output)
521          double precision (or double complex) values(maxcols) output
522 .ve
523    where maxcols >= maximum nonzeros in any row of the matrix.
524 
525    Caution:
526    Do not try to change the contents of the output arrays (cols and vals).
527    In some cases, this may corrupt the matrix.
528 
529    Level: advanced
530 
531 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
532 @*/
533 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) {
534   PetscInt incols;
535 
536   PetscFunctionBegin;
537   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
538   PetscValidType(mat, 1);
539   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
540   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
541   MatCheckPreallocated(mat, 1);
542   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);
543   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
544   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
545   if (ncols) *ncols = incols;
546   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
547   PetscFunctionReturn(0);
548 }
549 
550 /*@
551    MatConjugate - replaces the matrix values with their complex conjugates
552 
553    Logically Collective on Mat
554 
555    Input Parameters:
556 .  mat - the matrix
557 
558    Level: advanced
559 
560 .seealso: `VecConjugate()`, `MatTranspose()`
561 @*/
562 PetscErrorCode MatConjugate(Mat mat) {
563   PetscFunctionBegin;
564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
565   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
566   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
567     PetscUseTypeMethod(mat, conjugate);
568     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
569   }
570   PetscFunctionReturn(0);
571 }
572 
573 /*@C
574    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
575 
576    Not Collective
577 
578    Input Parameters:
579 +  mat - the matrix
580 .  row - the row to get
581 .  ncols, cols - the number of nonzeros and their columns
582 -  vals - if nonzero the column values
583 
584    Notes:
585    This routine should be called after you have finished examining the entries.
586 
587    This routine zeros out ncols, cols, and vals. This is to prevent accidental
588    us of the array after it has been restored. If you pass NULL, it will
589    not zero the pointers.  Use of cols or vals after `MatRestoreRow()` is invalid.
590 
591    Fortran Notes:
592    The calling sequence from Fortran is
593 .vb
594    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
595       Mat     matrix (input)
596       integer row    (input)
597       integer ncols  (output)
598       integer cols(maxcols) (output)
599       double precision (or double complex) values(maxcols) output
600 .ve
601    Where maxcols >= maximum nonzeros in any row of the matrix.
602 
603    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
604    before another call to `MatGetRow()` can be made.
605 
606    Level: advanced
607 
608 .seealso: `MatGetRow()`
609 @*/
610 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) {
611   PetscFunctionBegin;
612   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
613   if (ncols) PetscValidIntPointer(ncols, 3);
614   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
615   if (!mat->ops->restorerow) PetscFunctionReturn(0);
616   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
617   if (ncols) *ncols = 0;
618   if (cols) *cols = NULL;
619   if (vals) *vals = NULL;
620   PetscFunctionReturn(0);
621 }
622 
623 /*@
624    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
625    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
626 
627    Not Collective
628 
629    Input Parameters:
630 .  mat - the matrix
631 
632    Notes:
633    The flag is to ensure that users are aware of `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
634 
635    Level: advanced
636 
637 .seealso: `MatRestoreRowUpperTriangular()`
638 @*/
639 PetscErrorCode MatGetRowUpperTriangular(Mat mat) {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   PetscValidType(mat, 1);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
645   MatCheckPreallocated(mat, 1);
646   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
647   PetscUseTypeMethod(mat, getrowuppertriangular);
648   PetscFunctionReturn(0);
649 }
650 
651 /*@
652    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
653 
654    Not Collective
655 
656    Input Parameters:
657 .  mat - the matrix
658 
659    Notes:
660    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
661 
662    Level: advanced
663 
664 .seealso: `MatGetRowUpperTriangular()`
665 @*/
666 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) {
667   PetscFunctionBegin;
668   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
669   PetscValidType(mat, 1);
670   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
671   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
672   MatCheckPreallocated(mat, 1);
673   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
674   PetscUseTypeMethod(mat, restorerowuppertriangular);
675   PetscFunctionReturn(0);
676 }
677 
678 /*@C
679    MatSetOptionsPrefix - Sets the prefix used for searching for all
680    Mat options in the database.
681 
682    Logically Collective on Mat
683 
684    Input Parameters:
685 +  A - the Mat context
686 -  prefix - the prefix to prepend to all option names
687 
688    Notes:
689    A hyphen (-) must NOT be given at the beginning of the prefix name.
690    The first character of all runtime options is AUTOMATICALLY the hyphen.
691 
692    This is NOT used for options for the factorization of the matrix. Normally the
693    prefix is automatically passed in from the PC calling the factorization. To set
694    it directly use  `MatSetOptionsPrefixFactor()`
695 
696    Level: advanced
697 
698 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
699 @*/
700 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) {
701   PetscFunctionBegin;
702   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
703   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
704   PetscFunctionReturn(0);
705 }
706 
707 /*@C
708    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all Mat factor options in the database for
709    for matrices created with `MatGetFactor()`
710 
711    Logically Collective on Mat
712 
713    Input Parameters:
714 +  A - the Mat context
715 -  prefix - the prefix to prepend to all option names for the factored matrix
716 
717    Notes:
718    A hyphen (-) must NOT be given at the beginning of the prefix name.
719    The first character of all runtime options is AUTOMATICALLY the hyphen.
720 
721    Normally the prefix is automatically passed in from the PC calling the factorization. To set
722    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
723 
724    Level: developer
725 
726 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
727 @*/
728 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) {
729   PetscFunctionBegin;
730   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
731   if (prefix) {
732     PetscValidCharPointer(prefix, 2);
733     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
734     if (prefix != A->factorprefix) {
735       PetscCall(PetscFree(A->factorprefix));
736       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
737     }
738   } else PetscCall(PetscFree(A->factorprefix));
739   PetscFunctionReturn(0);
740 }
741 
742 /*@C
743    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all Mat factor options in the database for
744    for matrices created with `MatGetFactor()`
745 
746    Logically Collective on Mat
747 
748    Input Parameters:
749 +  A - the Mat context
750 -  prefix - the prefix to prepend to all option names for the factored matrix
751 
752    Notes:
753    A hyphen (-) must NOT be given at the beginning of the prefix name.
754    The first character of all runtime options is AUTOMATICALLY the hyphen.
755 
756    Normally the prefix is automatically passed in from the PC calling the factorization. To set
757    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
758 
759    Level: developer
760    .seealso: `PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
761              `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
762              `MatSetOptionsPrefix()`
763 @*/
764 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) {
765   char  *buf = A->factorprefix;
766   size_t len1, len2;
767 
768   PetscFunctionBegin;
769   PetscValidHeader(A, 1);
770   if (!prefix) PetscFunctionReturn(0);
771   if (!buf) {
772     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
773     PetscFunctionReturn(0);
774   }
775   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
776 
777   PetscCall(PetscStrlen(prefix, &len1));
778   PetscCall(PetscStrlen(buf, &len2));
779   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
780   PetscCall(PetscStrcpy(A->factorprefix, buf));
781   PetscCall(PetscStrcat(A->factorprefix, prefix));
782   PetscCall(PetscFree(buf));
783   PetscFunctionReturn(0);
784 }
785 
786 /*@C
787    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
788    Mat options in the database.
789 
790    Logically Collective on Mat
791 
792    Input Parameters:
793 +  A - the Mat context
794 -  prefix - the prefix to prepend to all option names
795 
796    Notes:
797    A hyphen (-) must NOT be given at the beginning of the prefix name.
798    The first character of all runtime options is AUTOMATICALLY the hyphen.
799 
800    Level: advanced
801 
802 .seealso: `MatGetOptionsPrefix()`
803 @*/
804 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) {
805   PetscFunctionBegin;
806   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
807   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
808   PetscFunctionReturn(0);
809 }
810 
811 /*@C
812    MatGetOptionsPrefix - Gets the prefix used for searching for all
813    Mat options in the database.
814 
815    Not Collective
816 
817    Input Parameter:
818 .  A - the Mat context
819 
820    Output Parameter:
821 .  prefix - pointer to the prefix string used
822 
823    Notes:
824     On the fortran side, the user should pass in a string 'prefix' of
825    sufficient length to hold the prefix.
826 
827    Level: advanced
828 
829 .seealso: `MatAppendOptionsPrefix()`
830 @*/
831 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) {
832   PetscFunctionBegin;
833   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
834   PetscValidPointer(prefix, 2);
835   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
836   PetscFunctionReturn(0);
837 }
838 
839 /*@
840    MatResetPreallocation - Reset mat to use the original nonzero pattern provided by users.
841 
842    Collective on Mat
843 
844    Input Parameters:
845 .  A - the Mat context
846 
847    Notes:
848    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
849 
850    Users can reset the preallocation to access the original memory.
851 
852    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.
853 
854    Level: beginner
855 
856 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
857 @*/
858 PetscErrorCode MatResetPreallocation(Mat A) {
859   PetscFunctionBegin;
860   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
861   PetscValidType(A, 1);
862   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
863   PetscFunctionReturn(0);
864 }
865 
866 /*@
867    MatSetUp - Sets up the internal matrix data structures for later use.
868 
869    Collective on Mat
870 
871    Input Parameters:
872 .  A - the Mat context
873 
874    Notes:
875    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
876 
877    If a suitable preallocation routine is used, this function does not need to be called.
878 
879    See the Performance chapter of the PETSc users manual for how to preallocate matrices
880 
881    Level: beginner
882 
883 .seealso: `MatCreate()`, `MatDestroy()`
884 @*/
885 PetscErrorCode MatSetUp(Mat A) {
886   PetscFunctionBegin;
887   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
888   if (!((PetscObject)A)->type_name) {
889     PetscMPIInt size;
890 
891     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
892     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
893   }
894   if (!A->preallocated && A->ops->setup) {
895     PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n"));
896     PetscUseTypeMethod(A, setup);
897   }
898   PetscCall(PetscLayoutSetUp(A->rmap));
899   PetscCall(PetscLayoutSetUp(A->cmap));
900   A->preallocated = PETSC_TRUE;
901   PetscFunctionReturn(0);
902 }
903 
904 #if defined(PETSC_HAVE_SAWS)
905 #include <petscviewersaws.h>
906 #endif
907 
908 /*@C
909    MatViewFromOptions - View from Options
910 
911    Collective on Mat
912 
913    Input Parameters:
914 +  A - the Mat context
915 .  obj - Optional object
916 -  name - command line option
917 
918    Level: intermediate
919 .seealso: `Mat`, `MatView`, `PetscObjectViewFromOptions()`, `MatCreate()`
920 @*/
921 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) {
922   PetscFunctionBegin;
923   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
924   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
925   PetscFunctionReturn(0);
926 }
927 
928 /*@C
929    MatView - Visualizes a matrix object.
930 
931    Collective on Mat
932 
933    Input Parameters:
934 +  mat - the matrix
935 -  viewer - visualization context
936 
937   Notes:
938   The available visualization contexts include
939 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
940 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
941 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
942 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
943 
944    The user can open alternative visualization contexts with
945 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
946 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
947          specified file; corresponding input uses MatLoad()
948 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
949          an X window display
950 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
951          Currently only the sequential dense and AIJ
952          matrix types support the Socket viewer.
953 
954    The user can call `PetscViewerPushFormat()` to specify the output
955    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
956    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
957 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
958 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
959 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
960 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
961          format common among all matrix types
962 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
963          format (which is in many cases the same as the default)
964 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
965          size and structure (not the matrix entries)
966 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
967          the matrix structure
968 
969    Options Database Keys:
970 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
971 .  -mat_view ::ascii_info_detail - Prints more detailed info
972 .  -mat_view - Prints matrix in ASCII format
973 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
974 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
975 .  -display <name> - Sets display name (default is host)
976 .  -draw_pause <sec> - Sets number of seconds to pause after display
977 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
978 .  -viewer_socket_machine <machine> -
979 .  -viewer_socket_port <port> -
980 .  -mat_view binary - save matrix to file in binary format
981 -  -viewer_binary_filename <name> -
982 
983    Level: beginner
984 
985    Notes:
986     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
987     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
988 
989     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
990 
991     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
992       viewer is used.
993 
994       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
995       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
996 
997       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
998       and then use the following mouse functions.
999 .vb
1000   left mouse: zoom in
1001   middle mouse: zoom out
1002   right mouse: continue with the simulation
1003 .ve
1004 
1005 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`,
1006           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`
1007 @*/
1008 PetscErrorCode MatView(Mat mat, PetscViewer viewer) {
1009   PetscInt          rows, cols, rbs, cbs;
1010   PetscBool         isascii, isstring, issaws;
1011   PetscViewerFormat format;
1012   PetscMPIInt       size;
1013 
1014   PetscFunctionBegin;
1015   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1016   PetscValidType(mat, 1);
1017   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1018   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1019   PetscCheckSameComm(mat, 1, viewer, 2);
1020   MatCheckPreallocated(mat, 1);
1021 
1022   PetscCall(PetscViewerGetFormat(viewer, &format));
1023   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1024   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1025 
1026   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1027   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1028   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1029   if ((!isascii || (format != PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) && mat->factortype) {
1030     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII info or info_detail");
1031   }
1032 
1033   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1034   if (isascii) {
1035     PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Must call MatAssemblyBegin/End() before viewing matrix");
1036     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1037     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1038       MatNullSpace nullsp, transnullsp;
1039 
1040       PetscCall(PetscViewerASCIIPushTab(viewer));
1041       PetscCall(MatGetSize(mat, &rows, &cols));
1042       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1043       if (rbs != 1 || cbs != 1) {
1044         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1045         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1046       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1047       if (mat->factortype) {
1048         MatSolverType solver;
1049         PetscCall(MatFactorGetSolverType(mat, &solver));
1050         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1051       }
1052       if (mat->ops->getinfo) {
1053         MatInfo info;
1054         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1055         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1056         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1057       }
1058       PetscCall(MatGetNullSpace(mat, &nullsp));
1059       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1060       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1061       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1062       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1063       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1064       PetscCall(PetscViewerASCIIPushTab(viewer));
1065       PetscCall(MatProductView(mat, viewer));
1066       PetscCall(PetscViewerASCIIPopTab(viewer));
1067     }
1068   } else if (issaws) {
1069 #if defined(PETSC_HAVE_SAWS)
1070     PetscMPIInt rank;
1071 
1072     PetscCall(PetscObjectName((PetscObject)mat));
1073     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1074     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1075 #endif
1076   } else if (isstring) {
1077     const char *type;
1078     PetscCall(MatGetType(mat, &type));
1079     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1080     PetscTryTypeMethod(mat, view, viewer);
1081   }
1082   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1083     PetscCall(PetscViewerASCIIPushTab(viewer));
1084     PetscUseTypeMethod(mat, viewnative, viewer);
1085     PetscCall(PetscViewerASCIIPopTab(viewer));
1086   } else if (mat->ops->view) {
1087     PetscCall(PetscViewerASCIIPushTab(viewer));
1088     PetscUseTypeMethod(mat, view, viewer);
1089     PetscCall(PetscViewerASCIIPopTab(viewer));
1090   }
1091   if (isascii) {
1092     PetscCall(PetscViewerGetFormat(viewer, &format));
1093     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1094   }
1095   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1096   PetscFunctionReturn(0);
1097 }
1098 
1099 #if defined(PETSC_USE_DEBUG)
1100 #include <../src/sys/totalview/tv_data_display.h>
1101 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) {
1102   TV_add_row("Local rows", "int", &mat->rmap->n);
1103   TV_add_row("Local columns", "int", &mat->cmap->n);
1104   TV_add_row("Global rows", "int", &mat->rmap->N);
1105   TV_add_row("Global columns", "int", &mat->cmap->N);
1106   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1107   return TV_format_OK;
1108 }
1109 #endif
1110 
1111 /*@C
1112    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1113    with `MatView()`.  The matrix format is determined from the options database.
1114    Generates a parallel MPI matrix if the communicator has more than one
1115    processor.  The default matrix type is AIJ.
1116 
1117    Collective on PetscViewer
1118 
1119    Input Parameters:
1120 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1121             or some related function before a call to `MatLoad()`
1122 -  viewer - binary/HDF5 file viewer
1123 
1124    Options Database Keys:
1125    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1126    block size
1127 .    -matload_block_size <bs> - set block size
1128 
1129    Level: beginner
1130 
1131    Notes:
1132    If the Mat type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1133    Mat before calling this routine if you wish to set it from the options database.
1134 
1135    `MatLoad()` automatically loads into the options database any options
1136    given in the file filename.info where filename is the name of the file
1137    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1138    file will be ignored if you use the -viewer_binary_skip_info option.
1139 
1140    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1141    sets the default matrix type AIJ and sets the local and global sizes.
1142    If type and/or size is already set, then the same are used.
1143 
1144    In parallel, each processor can load a subset of rows (or the
1145    entire matrix).  This routine is especially useful when a large
1146    matrix is stored on disk and only part of it is desired on each
1147    processor.  For example, a parallel solver may access only some of
1148    the rows from each processor.  The algorithm used here reads
1149    relatively small blocks of data rather than reading the entire
1150    matrix and then subsetting it.
1151 
1152    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1153    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1154    or the sequence like
1155 .vb
1156     `PetscViewer` v;
1157     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1158     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1159     `PetscViewerSetFromOptions`(v);
1160     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1161     `PetscViewerFileSetName`(v,"datafile");
1162 .ve
1163    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1164 $ -viewer_type {binary,hdf5}
1165 
1166    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1167    and src/mat/tutorials/ex10.c with the second approach.
1168 
1169    Notes about the PETSc binary format:
1170    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1171    is read onto rank 0 and then shipped to its destination rank, one after another.
1172    Multiple objects, both matrices and vectors, can be stored within the same file.
1173    Their PetscObject name is ignored; they are loaded in the order of their storage.
1174 
1175    Most users should not need to know the details of the binary storage
1176    format, since `MatLoad()` and `MatView()` completely hide these details.
1177    But for anyone who's interested, the standard binary matrix storage
1178    format is
1179 
1180 $    PetscInt    MAT_FILE_CLASSID
1181 $    PetscInt    number of rows
1182 $    PetscInt    number of columns
1183 $    PetscInt    total number of nonzeros
1184 $    PetscInt    *number nonzeros in each row
1185 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1186 $    PetscScalar *values of all nonzeros
1187 
1188    PETSc automatically does the byte swapping for
1189 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1190 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1191 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1192 and `PetscBinaryWrite()` to see how this may be done.
1193 
1194    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1195    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1196    Each processor's chunk is loaded independently by its owning rank.
1197    Multiple objects, both matrices and vectors, can be stored within the same file.
1198    They are looked up by their PetscObject name.
1199 
1200    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1201    by default the same structure and naming of the AIJ arrays and column count
1202    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1203 $    save example.mat A b -v7.3
1204    can be directly read by this routine (see Reference 1 for details).
1205    Note that depending on your MATLAB version, this format might be a default,
1206    otherwise you can set it as default in Preferences.
1207 
1208    Unless -nocompression flag is used to save the file in MATLAB,
1209    PETSc must be configured with ZLIB package.
1210 
1211    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1212 
1213    Current HDF5 (MAT-File) limitations:
1214    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1215 
1216    Corresponding `MatView()` is not yet implemented.
1217 
1218    The loaded matrix is actually a transpose of the original one in MATLAB,
1219    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1220    With this format, matrix is automatically transposed by PETSc,
1221    unless the matrix is marked as SPD or symmetric
1222    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1223 
1224    References:
1225 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1226 
1227 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1228 
1229  @*/
1230 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) {
1231   PetscBool flg;
1232 
1233   PetscFunctionBegin;
1234   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1235   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1236 
1237   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1238 
1239   flg = PETSC_FALSE;
1240   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1241   if (flg) {
1242     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1243     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1244   }
1245   flg = PETSC_FALSE;
1246   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1247   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1248 
1249   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1250   PetscUseTypeMethod(mat, load, viewer);
1251   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1252   PetscFunctionReturn(0);
1253 }
1254 
1255 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) {
1256   Mat_Redundant *redund = *redundant;
1257 
1258   PetscFunctionBegin;
1259   if (redund) {
1260     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1261       PetscCall(ISDestroy(&redund->isrow));
1262       PetscCall(ISDestroy(&redund->iscol));
1263       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1264     } else {
1265       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1266       PetscCall(PetscFree(redund->sbuf_j));
1267       PetscCall(PetscFree(redund->sbuf_a));
1268       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1269         PetscCall(PetscFree(redund->rbuf_j[i]));
1270         PetscCall(PetscFree(redund->rbuf_a[i]));
1271       }
1272       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1273     }
1274 
1275     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1276     PetscCall(PetscFree(redund));
1277   }
1278   PetscFunctionReturn(0);
1279 }
1280 
1281 /*@C
1282    MatDestroy - Frees space taken by a matrix.
1283 
1284    Collective on Mat
1285 
1286    Input Parameter:
1287 .  A - the matrix
1288 
1289    Level: beginner
1290 
1291    Developer Notes:
1292    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1293    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1294    MatHeaderMerge() and MatHeaderReplace() also manipulate the data in the `Mat` object and likely need changes
1295    if changes are needed here.
1296 @*/
1297 PetscErrorCode MatDestroy(Mat *A) {
1298   PetscFunctionBegin;
1299   if (!*A) PetscFunctionReturn(0);
1300   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1301   if (--((PetscObject)(*A))->refct > 0) {
1302     *A = NULL;
1303     PetscFunctionReturn(0);
1304   }
1305 
1306   /* if memory was published with SAWs then destroy it */
1307   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1308   PetscTryTypeMethod((*A), destroy);
1309 
1310   PetscCall(PetscFree((*A)->factorprefix));
1311   PetscCall(PetscFree((*A)->defaultvectype));
1312   PetscCall(PetscFree((*A)->bsizes));
1313   PetscCall(PetscFree((*A)->solvertype));
1314   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1315   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1316   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1317   PetscCall(MatProductClear(*A));
1318   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1319   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1320   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1321   PetscCall(MatDestroy(&(*A)->schur));
1322   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1323   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1324   PetscCall(PetscHeaderDestroy(A));
1325   PetscFunctionReturn(0);
1326 }
1327 
1328 /*@C
1329    MatSetValues - Inserts or adds a block of values into a matrix.
1330    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1331    MUST be called after all calls to `MatSetValues()` have been completed.
1332 
1333    Not Collective
1334 
1335    Input Parameters:
1336 +  mat - the matrix
1337 .  v - a logically two-dimensional array of values
1338 .  m, idxm - the number of rows and their global indices
1339 .  n, idxn - the number of columns and their global indices
1340 -  addv - either `ADD_VALUES` or `INSERT_VALUES`, where
1341    `ADD_VALUES` adds values to any existing entries, and
1342    `INSERT_VALUES` replaces existing entries with new values
1343 
1344    Notes:
1345    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1346       `MatSetUp()` before using this routine
1347 
1348    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1349 
1350    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1351    options cannot be mixed without intervening calls to the assembly
1352    routines.
1353 
1354    `MatSetValues()` uses 0-based row and column numbers in Fortran
1355    as well as in C.
1356 
1357    Negative indices may be passed in idxm and idxn, these rows and columns are
1358    simply ignored. This allows easily inserting element stiffness matrices
1359    with homogeneous Dirchlet boundary conditions that you don't want represented
1360    in the matrix.
1361 
1362    Efficiency Alert:
1363    The routine `MatSetValuesBlocked()` may offer much better efficiency
1364    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1365 
1366    Level: beginner
1367 
1368    Developer Notes:
1369    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1370    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1371 
1372 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1373           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1374 @*/
1375 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) {
1376   PetscFunctionBeginHot;
1377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1378   PetscValidType(mat, 1);
1379   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1380   PetscValidIntPointer(idxm, 3);
1381   PetscValidIntPointer(idxn, 5);
1382   MatCheckPreallocated(mat, 1);
1383 
1384   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1385   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1386 
1387   if (PetscDefined(USE_DEBUG)) {
1388     PetscInt i, j;
1389 
1390     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1391     for (i = 0; i < m; i++) {
1392       for (j = 0; j < n; j++) {
1393         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1394 #if defined(PETSC_USE_COMPLEX)
1395           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]);
1396 #else
1397           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]);
1398 #endif
1399       }
1400     }
1401     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);
1402     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);
1403   }
1404 
1405   if (mat->assembled) {
1406     mat->was_assembled = PETSC_TRUE;
1407     mat->assembled     = PETSC_FALSE;
1408   }
1409   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1410   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1411   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1412   PetscFunctionReturn(0);
1413 }
1414 
1415 /*@C
1416    MatSetValuesIS - Inserts or adds a block of values into a matrix using IS to indicate the rows and columns
1417    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1418    MUST be called after all calls to `MatSetValues()` have been completed.
1419 
1420    Not Collective
1421 
1422    Input Parameters:
1423 +  mat - the matrix
1424 .  v - a logically two-dimensional array of values
1425 .  ism - the rows to provide
1426 .  isn - the columns to provide
1427 -  addv - either `ADD_VALUES` or `INSERT_VALUES`, where
1428    `ADD_VALUES` adds values to any existing entries, and
1429    `INSERT_VALUES` replaces existing entries with new values
1430 
1431    Notes:
1432    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1433       `MatSetUp()` before using this routine
1434 
1435    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1436 
1437    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1438    options cannot be mixed without intervening calls to the assembly
1439    routines.
1440 
1441    MatSetValues() uses 0-based row and column numbers in Fortran
1442    as well as in C.
1443 
1444    Negative indices may be passed in ism and isn, these rows and columns are
1445    simply ignored. This allows easily inserting element stiffness matrices
1446    with homogeneous Dirchlet boundary conditions that you don't want represented
1447    in the matrix.
1448 
1449    Efficiency Alert:
1450    The routine `MatSetValuesBlocked()` may offer much better efficiency
1451    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1452 
1453    Level: beginner
1454 
1455    Developer Notes:
1456     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1457                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1458 
1459     This is currently not optimized for any particular IS type
1460 
1461 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1462           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1463 @*/
1464 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) {
1465   PetscInt        m, n;
1466   const PetscInt *rows, *cols;
1467 
1468   PetscFunctionBeginHot;
1469   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1470   PetscCall(ISGetIndices(ism, &rows));
1471   PetscCall(ISGetIndices(isn, &cols));
1472   PetscCall(ISGetLocalSize(ism, &m));
1473   PetscCall(ISGetLocalSize(isn, &n));
1474   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1475   PetscCall(ISRestoreIndices(ism, &rows));
1476   PetscCall(ISRestoreIndices(isn, &cols));
1477   PetscFunctionReturn(0);
1478 }
1479 
1480 /*@
1481    MatSetValuesRowLocal - Inserts a row (block row for BAIJ matrices) of nonzero
1482         values into a matrix
1483 
1484    Not Collective
1485 
1486    Input Parameters:
1487 +  mat - the matrix
1488 .  row - the (block) row to set
1489 -  v - a logically two-dimensional array of values
1490 
1491    Notes:
1492    By the values, v, are column-oriented (for the block version) and sorted
1493 
1494    All the nonzeros in the row must be provided
1495 
1496    The matrix must have previously had its column indices set
1497 
1498    The row must belong to this process
1499 
1500    Level: intermediate
1501 
1502 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1503           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1504 @*/
1505 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) {
1506   PetscInt globalrow;
1507 
1508   PetscFunctionBegin;
1509   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1510   PetscValidType(mat, 1);
1511   PetscValidScalarPointer(v, 3);
1512   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1513   PetscCall(MatSetValuesRow(mat, globalrow, v));
1514   PetscFunctionReturn(0);
1515 }
1516 
1517 /*@
1518    MatSetValuesRow - Inserts a row (block row for BAIJ matrices) of nonzero
1519         values into a matrix
1520 
1521    Not Collective
1522 
1523    Input Parameters:
1524 +  mat - the matrix
1525 .  row - the (block) row to set
1526 -  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
1527 
1528    Notes:
1529    The values, v, are column-oriented for the block version.
1530 
1531    All the nonzeros in the row must be provided
1532 
1533    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1534 
1535    The row must belong to this process
1536 
1537    Level: advanced
1538 
1539 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1540           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1541 @*/
1542 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) {
1543   PetscFunctionBeginHot;
1544   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1545   PetscValidType(mat, 1);
1546   MatCheckPreallocated(mat, 1);
1547   PetscValidScalarPointer(v, 3);
1548   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1549   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1550   mat->insertmode = INSERT_VALUES;
1551 
1552   if (mat->assembled) {
1553     mat->was_assembled = PETSC_TRUE;
1554     mat->assembled     = PETSC_FALSE;
1555   }
1556   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1557   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1558   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1559   PetscFunctionReturn(0);
1560 }
1561 
1562 /*@
1563    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1564      Using structured grid indexing
1565 
1566    Not Collective
1567 
1568    Input Parameters:
1569 +  mat - the matrix
1570 .  m - number of rows being entered
1571 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1572 .  n - number of columns being entered
1573 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1574 .  v - a logically two-dimensional array of values
1575 -  addv - either ADD_VALUES or INSERT_VALUES, where
1576    ADD_VALUES adds values to any existing entries, and
1577    INSERT_VALUES replaces existing entries with new values
1578 
1579    Notes:
1580    By default the values, v, are row-oriented.  See `MatSetOption()` for other options.
1581 
1582    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1583    options cannot be mixed without intervening calls to the assembly
1584    routines.
1585 
1586    The grid coordinates are across the entire grid, not just the local portion
1587 
1588    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1589    as well as in C.
1590 
1591    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1592 
1593    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1594    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1595 
1596    The columns and rows in the stencil passed in MUST be contained within the
1597    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1598    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1599    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1600    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1601 
1602    In Fortran idxm and idxn should be declared as
1603 $     MatStencil idxm(4,m),idxn(4,n)
1604    and the values inserted using
1605 $    idxm(MatStencil_i,1) = i
1606 $    idxm(MatStencil_j,1) = j
1607 $    idxm(MatStencil_k,1) = k
1608 $    idxm(MatStencil_c,1) = c
1609    etc
1610 
1611    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1612    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1613    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1614    `DM_BOUNDARY_PERIODIC` boundary type.
1615 
1616    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
1617    a single value per point) you can skip filling those indices.
1618 
1619    Inspired by the structured grid interface to the HYPRE package
1620    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1621 
1622    Efficiency Alert:
1623    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1624    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1625 
1626    Level: beginner
1627 
1628 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1629           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1630 @*/
1631 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) {
1632   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1633   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1634   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1635 
1636   PetscFunctionBegin;
1637   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1638   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1639   PetscValidType(mat, 1);
1640   PetscValidPointer(idxm, 3);
1641   PetscValidPointer(idxn, 5);
1642 
1643   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1644     jdxm = buf;
1645     jdxn = buf + m;
1646   } else {
1647     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1648     jdxm = bufm;
1649     jdxn = bufn;
1650   }
1651   for (i = 0; i < m; i++) {
1652     for (j = 0; j < 3 - sdim; j++) dxm++;
1653     tmp = *dxm++ - starts[0];
1654     for (j = 0; j < dim - 1; j++) {
1655       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1656       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1657     }
1658     if (mat->stencil.noc) dxm++;
1659     jdxm[i] = tmp;
1660   }
1661   for (i = 0; i < n; i++) {
1662     for (j = 0; j < 3 - sdim; j++) dxn++;
1663     tmp = *dxn++ - starts[0];
1664     for (j = 0; j < dim - 1; j++) {
1665       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1666       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1667     }
1668     if (mat->stencil.noc) dxn++;
1669     jdxn[i] = tmp;
1670   }
1671   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1672   PetscCall(PetscFree2(bufm, bufn));
1673   PetscFunctionReturn(0);
1674 }
1675 
1676 /*@
1677    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1678      Using structured grid indexing
1679 
1680    Not Collective
1681 
1682    Input Parameters:
1683 +  mat - the matrix
1684 .  m - number of rows being entered
1685 .  idxm - grid coordinates for matrix rows being entered
1686 .  n - number of columns being entered
1687 .  idxn - grid coordinates for matrix columns being entered
1688 .  v - a logically two-dimensional array of values
1689 -  addv - either ADD_VALUES or INSERT_VALUES, where
1690    ADD_VALUES adds values to any existing entries, and
1691    INSERT_VALUES replaces existing entries with new values
1692 
1693    Notes:
1694    By default the values, v, are row-oriented and unsorted.
1695    See MatSetOption() for other options.
1696 
1697    Calls to MatSetValuesBlockedStencil() with the INSERT_VALUES and ADD_VALUES
1698    options cannot be mixed without intervening calls to the assembly
1699    routines.
1700 
1701    The grid coordinates are across the entire grid, not just the local portion
1702 
1703    MatSetValuesBlockedStencil() uses 0-based row and column numbers in Fortran
1704    as well as in C.
1705 
1706    For setting/accessing vector values via array coordinates you can use the DMDAVecGetArray() routine
1707 
1708    In order to use this routine you must either obtain the matrix with DMCreateMatrix()
1709    or call MatSetBlockSize(), MatSetLocalToGlobalMapping() and MatSetStencil() first.
1710 
1711    The columns and rows in the stencil passed in MUST be contained within the
1712    ghost region of the given process as set with DMDACreateXXX() or MatSetStencil(). For example,
1713    if you create a DMDA with an overlap of one grid level and on a particular process its first
1714    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1715    first i index you can use in your column and row indices in MatSetStencil() is 5.
1716 
1717    In Fortran idxm and idxn should be declared as
1718 $     MatStencil idxm(4,m),idxn(4,n)
1719    and the values inserted using
1720 $    idxm(MatStencil_i,1) = i
1721 $    idxm(MatStencil_j,1) = j
1722 $    idxm(MatStencil_k,1) = k
1723    etc
1724 
1725    Negative indices may be passed in idxm and idxn, these rows and columns are
1726    simply ignored. This allows easily inserting element stiffness matrices
1727    with homogeneous Dirchlet boundary conditions that you don't want represented
1728    in the matrix.
1729 
1730    Inspired by the structured grid interface to the HYPRE package
1731    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1732 
1733    Level: beginner
1734 
1735 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1736           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1737           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1738 @*/
1739 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) {
1740   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1741   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1742   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1743 
1744   PetscFunctionBegin;
1745   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1746   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1747   PetscValidType(mat, 1);
1748   PetscValidPointer(idxm, 3);
1749   PetscValidPointer(idxn, 5);
1750   PetscValidScalarPointer(v, 6);
1751 
1752   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1753     jdxm = buf;
1754     jdxn = buf + m;
1755   } else {
1756     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1757     jdxm = bufm;
1758     jdxn = bufn;
1759   }
1760   for (i = 0; i < m; i++) {
1761     for (j = 0; j < 3 - sdim; j++) dxm++;
1762     tmp = *dxm++ - starts[0];
1763     for (j = 0; j < sdim - 1; j++) {
1764       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1765       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1766     }
1767     dxm++;
1768     jdxm[i] = tmp;
1769   }
1770   for (i = 0; i < n; i++) {
1771     for (j = 0; j < 3 - sdim; j++) dxn++;
1772     tmp = *dxn++ - starts[0];
1773     for (j = 0; j < sdim - 1; j++) {
1774       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1775       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1776     }
1777     dxn++;
1778     jdxn[i] = tmp;
1779   }
1780   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1781   PetscCall(PetscFree2(bufm, bufn));
1782   PetscFunctionReturn(0);
1783 }
1784 
1785 /*@
1786    MatSetStencil - Sets the grid information for setting values into a matrix via
1787         MatSetValuesStencil()
1788 
1789    Not Collective
1790 
1791    Input Parameters:
1792 +  mat - the matrix
1793 .  dim - dimension of the grid 1, 2, or 3
1794 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1795 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1796 -  dof - number of degrees of freedom per node
1797 
1798    Inspired by the structured grid interface to the HYPRE package
1799    (www.llnl.gov/CASC/hyper)
1800 
1801    For matrices generated with DMCreateMatrix() this routine is automatically called and so not needed by the
1802    user.
1803 
1804    Level: beginner
1805 
1806 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1807           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1808 @*/
1809 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) {
1810   PetscFunctionBegin;
1811   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1812   PetscValidIntPointer(dims, 3);
1813   PetscValidIntPointer(starts, 4);
1814 
1815   mat->stencil.dim = dim + (dof > 1);
1816   for (PetscInt i = 0; i < dim; i++) {
1817     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1818     mat->stencil.starts[i] = starts[dim - i - 1];
1819   }
1820   mat->stencil.dims[dim]   = dof;
1821   mat->stencil.starts[dim] = 0;
1822   mat->stencil.noc         = (PetscBool)(dof == 1);
1823   PetscFunctionReturn(0);
1824 }
1825 
1826 /*@C
1827    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1828 
1829    Not Collective
1830 
1831    Input Parameters:
1832 +  mat - the matrix
1833 .  v - a logically two-dimensional array of values
1834 .  m, idxm - the number of block rows and their global block indices
1835 .  n, idxn - the number of block columns and their global block indices
1836 -  addv - either ADD_VALUES or INSERT_VALUES, where
1837    ADD_VALUES adds values to any existing entries, and
1838    INSERT_VALUES replaces existing entries with new values
1839 
1840    Notes:
1841    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call
1842    MatXXXXSetPreallocation() or MatSetUp() before using this routine.
1843 
1844    The m and n count the NUMBER of blocks in the row direction and column direction,
1845    NOT the total number of rows/columns; for example, if the block size is 2 and
1846    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1847    The values in idxm would be 1 2; that is the first index for each block divided by
1848    the block size.
1849 
1850    Note that you must call MatSetBlockSize() when constructing this matrix (before
1851    preallocating it).
1852 
1853    By default the values, v, are row-oriented, so the layout of
1854    v is the same as for MatSetValues(). See MatSetOption() for other options.
1855 
1856    Calls to MatSetValuesBlocked() with the INSERT_VALUES and ADD_VALUES
1857    options cannot be mixed without intervening calls to the assembly
1858    routines.
1859 
1860    MatSetValuesBlocked() uses 0-based row and column numbers in Fortran
1861    as well as in C.
1862 
1863    Negative indices may be passed in idxm and idxn, these rows and columns are
1864    simply ignored. This allows easily inserting element stiffness matrices
1865    with homogeneous Dirchlet boundary conditions that you don't want represented
1866    in the matrix.
1867 
1868    Each time an entry is set within a sparse matrix via MatSetValues(),
1869    internal searching must be done to determine where to place the
1870    data in the matrix storage space.  By instead inserting blocks of
1871    entries via MatSetValuesBlocked(), the overhead of matrix assembly is
1872    reduced.
1873 
1874    Example:
1875 $   Suppose m=n=2 and block size(bs) = 2 The array is
1876 $
1877 $   1  2  | 3  4
1878 $   5  6  | 7  8
1879 $   - - - | - - -
1880 $   9  10 | 11 12
1881 $   13 14 | 15 16
1882 $
1883 $   v[] should be passed in like
1884 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1885 $
1886 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1887 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1888 
1889    Level: intermediate
1890 
1891 .seealso: `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1892 @*/
1893 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) {
1894   PetscFunctionBeginHot;
1895   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1896   PetscValidType(mat, 1);
1897   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1898   PetscValidIntPointer(idxm, 3);
1899   PetscValidIntPointer(idxn, 5);
1900   MatCheckPreallocated(mat, 1);
1901   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1902   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1903   if (PetscDefined(USE_DEBUG)) {
1904     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1905     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1906   }
1907   if (PetscDefined(USE_DEBUG)) {
1908     PetscInt rbs, cbs, M, N, i;
1909     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1910     PetscCall(MatGetSize(mat, &M, &N));
1911     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);
1912     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);
1913   }
1914   if (mat->assembled) {
1915     mat->was_assembled = PETSC_TRUE;
1916     mat->assembled     = PETSC_FALSE;
1917   }
1918   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1919   if (mat->ops->setvaluesblocked) {
1920     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1921   } else {
1922     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1923     PetscInt i, j, bs, cbs;
1924 
1925     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1926     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1927       iidxm = buf;
1928       iidxn = buf + m * bs;
1929     } else {
1930       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1931       iidxm = bufr;
1932       iidxn = bufc;
1933     }
1934     for (i = 0; i < m; i++) {
1935       for (j = 0; j < bs; j++) { iidxm[i * bs + j] = bs * idxm[i] + j; }
1936     }
1937     if (m != n || bs != cbs || idxm != idxn) {
1938       for (i = 0; i < n; i++) {
1939         for (j = 0; j < cbs; j++) { iidxn[i * cbs + j] = cbs * idxn[i] + j; }
1940       }
1941     } else iidxn = iidxm;
1942     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
1943     PetscCall(PetscFree2(bufr, bufc));
1944   }
1945   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1946   PetscFunctionReturn(0);
1947 }
1948 
1949 /*@C
1950    MatGetValues - Gets a block of values from a matrix.
1951 
1952    Not Collective; can only return values that are owned by the give process
1953 
1954    Input Parameters:
1955 +  mat - the matrix
1956 .  v - a logically two-dimensional array for storing the values
1957 .  m, idxm - the number of rows and their global indices
1958 -  n, idxn - the number of columns and their global indices
1959 
1960    Notes:
1961      The user must allocate space (m*n PetscScalars) for the values, v.
1962      The values, v, are then returned in a row-oriented format,
1963      analogous to that used by default in MatSetValues().
1964 
1965      MatGetValues() uses 0-based row and column numbers in
1966      Fortran as well as in C.
1967 
1968      MatGetValues() requires that the matrix has been assembled
1969      with MatAssemblyBegin()/MatAssemblyEnd().  Thus, calls to
1970      MatSetValues() and MatGetValues() CANNOT be made in succession
1971      without intermediate matrix assembly.
1972 
1973      Negative row or column indices will be ignored and those locations in v[] will be
1974      left unchanged.
1975 
1976      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
1977      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
1978      from MatGetOwnershipRange(mat,&rstart,&rend).
1979 
1980    Level: advanced
1981 
1982 .seealso: `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
1983 @*/
1984 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) {
1985   PetscFunctionBegin;
1986   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1987   PetscValidType(mat, 1);
1988   if (!m || !n) PetscFunctionReturn(0);
1989   PetscValidIntPointer(idxm, 3);
1990   PetscValidIntPointer(idxn, 5);
1991   PetscValidScalarPointer(v, 6);
1992   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
1993   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1994   MatCheckPreallocated(mat, 1);
1995 
1996   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
1997   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
1998   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
1999   PetscFunctionReturn(0);
2000 }
2001 
2002 /*@C
2003    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2004      defined previously by MatSetLocalToGlobalMapping()
2005 
2006    Not Collective
2007 
2008    Input Parameters:
2009 +  mat - the matrix
2010 .  nrow, irow - number of rows and their local indices
2011 -  ncol, icol - number of columns and their local indices
2012 
2013    Output Parameter:
2014 .  y -  a logically two-dimensional array of values
2015 
2016    Notes:
2017      If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine.
2018 
2019      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,
2020      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from MatGetOwnershipRange(mat,&rstart,&rend). One can
2021      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the ISLocalToGlobalMapping set
2022      with MatSetLocalToGlobalMapping().
2023 
2024    Developer Notes:
2025       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2026       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2027 
2028    Level: advanced
2029 
2030 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2031           `MatSetValuesLocal()`, `MatGetValues()`
2032 @*/
2033 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) {
2034   PetscFunctionBeginHot;
2035   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2036   PetscValidType(mat, 1);
2037   MatCheckPreallocated(mat, 1);
2038   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2039   PetscValidIntPointer(irow, 3);
2040   PetscValidIntPointer(icol, 5);
2041   if (PetscDefined(USE_DEBUG)) {
2042     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2043     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2044   }
2045   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2046   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2047   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2048   else {
2049     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2050     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2051       irowm = buf;
2052       icolm = buf + nrow;
2053     } else {
2054       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2055       irowm = bufr;
2056       icolm = bufc;
2057     }
2058     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2059     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2060     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2061     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2062     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2063     PetscCall(PetscFree2(bufr, bufc));
2064   }
2065   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2066   PetscFunctionReturn(0);
2067 }
2068 
2069 /*@
2070   MatSetValuesBatch - Adds (ADD_VALUES) many blocks of values into a matrix at once. The blocks must all be square and
2071   the same size. Currently, this can only be called once and creates the given matrix.
2072 
2073   Not Collective
2074 
2075   Input Parameters:
2076 + mat - the matrix
2077 . nb - the number of blocks
2078 . bs - the number of rows (and columns) in each block
2079 . rows - a concatenation of the rows for each block
2080 - v - a concatenation of logically two-dimensional arrays of values
2081 
2082   Notes:
2083   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2084 
2085   Level: advanced
2086 
2087 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2088           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
2089 @*/
2090 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) {
2091   PetscFunctionBegin;
2092   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2093   PetscValidType(mat, 1);
2094   PetscValidIntPointer(rows, 4);
2095   PetscValidScalarPointer(v, 5);
2096   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2097 
2098   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2099   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2100   else {
2101     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2102   }
2103   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2104   PetscFunctionReturn(0);
2105 }
2106 
2107 /*@
2108    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2109    the routine MatSetValuesLocal() to allow users to insert matrix entries
2110    using a local (per-processor) numbering.
2111 
2112    Not Collective
2113 
2114    Input Parameters:
2115 +  x - the matrix
2116 .  rmapping - row mapping created with ISLocalToGlobalMappingCreate() or ISLocalToGlobalMappingCreateIS()
2117 -  cmapping - column mapping
2118 
2119    Level: intermediate
2120 
2121 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2122 @*/
2123 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) {
2124   PetscFunctionBegin;
2125   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2126   PetscValidType(x, 1);
2127   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2128   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2129   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2130   else {
2131     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2132     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2133   }
2134   PetscFunctionReturn(0);
2135 }
2136 
2137 /*@
2138    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by MatSetLocalToGlobalMapping()
2139 
2140    Not Collective
2141 
2142    Input Parameter:
2143 .  A - the matrix
2144 
2145    Output Parameters:
2146 + rmapping - row mapping
2147 - cmapping - column mapping
2148 
2149    Level: advanced
2150 
2151 .seealso: `MatSetValuesLocal()`
2152 @*/
2153 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) {
2154   PetscFunctionBegin;
2155   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2156   PetscValidType(A, 1);
2157   if (rmapping) {
2158     PetscValidPointer(rmapping, 2);
2159     *rmapping = A->rmap->mapping;
2160   }
2161   if (cmapping) {
2162     PetscValidPointer(cmapping, 3);
2163     *cmapping = A->cmap->mapping;
2164   }
2165   PetscFunctionReturn(0);
2166 }
2167 
2168 /*@
2169    MatSetLayouts - Sets the PetscLayout objects for rows and columns of a matrix
2170 
2171    Logically Collective on A
2172 
2173    Input Parameters:
2174 +  A - the matrix
2175 . rmap - row layout
2176 - cmap - column layout
2177 
2178    Level: advanced
2179 
2180 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2181 @*/
2182 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) {
2183   PetscFunctionBegin;
2184   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2185   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2186   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2187   PetscFunctionReturn(0);
2188 }
2189 
2190 /*@
2191    MatGetLayouts - Gets the PetscLayout objects for rows and columns
2192 
2193    Not Collective
2194 
2195    Input Parameter:
2196 .  A - the matrix
2197 
2198    Output Parameters:
2199 + rmap - row layout
2200 - cmap - column layout
2201 
2202    Level: advanced
2203 
2204 .seealso: `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2205 @*/
2206 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) {
2207   PetscFunctionBegin;
2208   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2209   PetscValidType(A, 1);
2210   if (rmap) {
2211     PetscValidPointer(rmap, 2);
2212     *rmap = A->rmap;
2213   }
2214   if (cmap) {
2215     PetscValidPointer(cmap, 3);
2216     *cmap = A->cmap;
2217   }
2218   PetscFunctionReturn(0);
2219 }
2220 
2221 /*@C
2222    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2223    using a local numbering of the nodes.
2224 
2225    Not Collective
2226 
2227    Input Parameters:
2228 +  mat - the matrix
2229 .  nrow, irow - number of rows and their local indices
2230 .  ncol, icol - number of columns and their local indices
2231 .  y -  a logically two-dimensional array of values
2232 -  addv - either INSERT_VALUES or ADD_VALUES, where
2233    ADD_VALUES adds values to any existing entries, and
2234    INSERT_VALUES replaces existing entries with new values
2235 
2236    Notes:
2237    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2238       MatSetUp() before using this routine
2239 
2240    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetLocalToGlobalMapping() before using this routine
2241 
2242    Calls to MatSetValuesLocal() with the INSERT_VALUES and ADD_VALUES
2243    options cannot be mixed without intervening calls to the assembly
2244    routines.
2245 
2246    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2247    MUST be called after all calls to MatSetValuesLocal() have been completed.
2248 
2249    Level: intermediate
2250 
2251    Developer Notes:
2252     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2253                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2254 
2255 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2256           `MatSetValueLocal()`, `MatGetValuesLocal()`
2257 @*/
2258 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) {
2259   PetscFunctionBeginHot;
2260   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2261   PetscValidType(mat, 1);
2262   MatCheckPreallocated(mat, 1);
2263   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2264   PetscValidIntPointer(irow, 3);
2265   PetscValidIntPointer(icol, 5);
2266   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2267   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2268   if (PetscDefined(USE_DEBUG)) {
2269     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2270     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2271   }
2272 
2273   if (mat->assembled) {
2274     mat->was_assembled = PETSC_TRUE;
2275     mat->assembled     = PETSC_FALSE;
2276   }
2277   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2278   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2279   else {
2280     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2281     const PetscInt *irowm, *icolm;
2282 
2283     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2284       bufr  = buf;
2285       bufc  = buf + nrow;
2286       irowm = bufr;
2287       icolm = bufc;
2288     } else {
2289       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2290       irowm = bufr;
2291       icolm = bufc;
2292     }
2293     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2294     else irowm = irow;
2295     if (mat->cmap->mapping) {
2296       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2297         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2298       } else icolm = irowm;
2299     } else icolm = icol;
2300     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2301     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2302   }
2303   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2304   PetscFunctionReturn(0);
2305 }
2306 
2307 /*@C
2308    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2309    using a local ordering of the nodes a block at a time.
2310 
2311    Not Collective
2312 
2313    Input Parameters:
2314 +  x - the matrix
2315 .  nrow, irow - number of rows and their local indices
2316 .  ncol, icol - number of columns and their local indices
2317 .  y -  a logically two-dimensional array of values
2318 -  addv - either INSERT_VALUES or ADD_VALUES, where
2319    ADD_VALUES adds values to any existing entries, and
2320    INSERT_VALUES replaces existing entries with new values
2321 
2322    Notes:
2323    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatXXXXSetPreallocation() or
2324       MatSetUp() before using this routine
2325 
2326    If you create the matrix yourself (that is not with a call to DMCreateMatrix()) then you MUST call MatSetBlockSize() and MatSetLocalToGlobalMapping()
2327       before using this routineBefore calling MatSetValuesLocal(), the user must first set the
2328 
2329    Calls to MatSetValuesBlockedLocal() with the INSERT_VALUES and ADD_VALUES
2330    options cannot be mixed without intervening calls to the assembly
2331    routines.
2332 
2333    These values may be cached, so MatAssemblyBegin() and MatAssemblyEnd()
2334    MUST be called after all calls to MatSetValuesBlockedLocal() have been completed.
2335 
2336    Level: intermediate
2337 
2338    Developer Notes:
2339     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2340                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2341 
2342 .seealso: `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2343           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2344 @*/
2345 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) {
2346   PetscFunctionBeginHot;
2347   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2348   PetscValidType(mat, 1);
2349   MatCheckPreallocated(mat, 1);
2350   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2351   PetscValidIntPointer(irow, 3);
2352   PetscValidIntPointer(icol, 5);
2353   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2354   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2355   if (PetscDefined(USE_DEBUG)) {
2356     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2357     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);
2358   }
2359 
2360   if (mat->assembled) {
2361     mat->was_assembled = PETSC_TRUE;
2362     mat->assembled     = PETSC_FALSE;
2363   }
2364   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2365     PetscInt irbs, rbs;
2366     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2367     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2368     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2369   }
2370   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2371     PetscInt icbs, cbs;
2372     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2373     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2374     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2375   }
2376   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2377   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2378   else {
2379     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2380     const PetscInt *irowm, *icolm;
2381 
2382     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2383       bufr  = buf;
2384       bufc  = buf + nrow;
2385       irowm = bufr;
2386       icolm = bufc;
2387     } else {
2388       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2389       irowm = bufr;
2390       icolm = bufc;
2391     }
2392     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2393     else irowm = irow;
2394     if (mat->cmap->mapping) {
2395       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2396         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2397       } else icolm = irowm;
2398     } else icolm = icol;
2399     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2400     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2401   }
2402   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2403   PetscFunctionReturn(0);
2404 }
2405 
2406 /*@
2407    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2408 
2409    Collective on Mat
2410 
2411    Input Parameters:
2412 +  mat - the matrix
2413 -  x   - the vector to be multiplied
2414 
2415    Output Parameters:
2416 .  y - the result
2417 
2418    Notes:
2419    The vectors x and y cannot be the same.  I.e., one cannot
2420    call MatMult(A,y,y).
2421 
2422    Level: developer
2423 
2424 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2425 @*/
2426 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) {
2427   PetscFunctionBegin;
2428   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2429   PetscValidType(mat, 1);
2430   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2431   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2432 
2433   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2434   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2435   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2436   MatCheckPreallocated(mat, 1);
2437 
2438   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2439   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2440   PetscFunctionReturn(0);
2441 }
2442 
2443 /* --------------------------------------------------------*/
2444 /*@
2445    MatMult - Computes the matrix-vector product, y = Ax.
2446 
2447    Neighbor-wise Collective on Mat
2448 
2449    Input Parameters:
2450 +  mat - the matrix
2451 -  x   - the vector to be multiplied
2452 
2453    Output Parameters:
2454 .  y - the result
2455 
2456    Notes:
2457    The vectors x and y cannot be the same.  I.e., one cannot
2458    call MatMult(A,y,y).
2459 
2460    Level: beginner
2461 
2462 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2463 @*/
2464 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) {
2465   PetscFunctionBegin;
2466   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2467   PetscValidType(mat, 1);
2468   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2469   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2470   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2471   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2472   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2473   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);
2474   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);
2475   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);
2476   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);
2477   PetscCall(VecSetErrorIfLocked(y, 3));
2478   if (mat->erroriffailure) PetscCall(VecValidValues(x, 2, PETSC_TRUE));
2479   MatCheckPreallocated(mat, 1);
2480 
2481   PetscCall(VecLockReadPush(x));
2482   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2483   PetscUseTypeMethod(mat, mult, x, y);
2484   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2485   if (mat->erroriffailure) PetscCall(VecValidValues(y, 3, PETSC_FALSE));
2486   PetscCall(VecLockReadPop(x));
2487   PetscFunctionReturn(0);
2488 }
2489 
2490 /*@
2491    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2492 
2493    Neighbor-wise Collective on Mat
2494 
2495    Input Parameters:
2496 +  mat - the matrix
2497 -  x   - the vector to be multiplied
2498 
2499    Output Parameters:
2500 .  y - the result
2501 
2502    Notes:
2503    The vectors x and y cannot be the same.  I.e., one cannot
2504    call MatMultTranspose(A,y,y).
2505 
2506    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2507    use MatMultHermitianTranspose()
2508 
2509    Level: beginner
2510 
2511 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2512 @*/
2513 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) {
2514   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2515 
2516   PetscFunctionBegin;
2517   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2518   PetscValidType(mat, 1);
2519   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2520   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2521 
2522   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2523   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2524   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2525   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);
2526   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);
2527   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);
2528   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);
2529   if (mat->erroriffailure) PetscCall(VecValidValues(x, 2, PETSC_TRUE));
2530   MatCheckPreallocated(mat, 1);
2531 
2532   if (!mat->ops->multtranspose) {
2533     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2534     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);
2535   } else op = mat->ops->multtranspose;
2536   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2537   PetscCall(VecLockReadPush(x));
2538   PetscCall((*op)(mat, x, y));
2539   PetscCall(VecLockReadPop(x));
2540   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2541   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2542   if (mat->erroriffailure) PetscCall(VecValidValues(y, 3, PETSC_FALSE));
2543   PetscFunctionReturn(0);
2544 }
2545 
2546 /*@
2547    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2548 
2549    Neighbor-wise Collective on Mat
2550 
2551    Input Parameters:
2552 +  mat - the matrix
2553 -  x   - the vector to be multilplied
2554 
2555    Output Parameters:
2556 .  y - the result
2557 
2558    Notes:
2559    The vectors x and y cannot be the same.  I.e., one cannot
2560    call MatMultHermitianTranspose(A,y,y).
2561 
2562    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2563 
2564    For real numbers MatMultTranspose() and MatMultHermitianTranspose() are identical.
2565 
2566    Level: beginner
2567 
2568 .seealso: `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2569 @*/
2570 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) {
2571   PetscFunctionBegin;
2572   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2573   PetscValidType(mat, 1);
2574   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2575   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2576 
2577   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2578   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2579   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2580   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);
2581   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);
2582   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);
2583   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);
2584   MatCheckPreallocated(mat, 1);
2585 
2586   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2587 #if defined(PETSC_USE_COMPLEX)
2588   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2589     PetscCall(VecLockReadPush(x));
2590     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2591     else PetscUseTypeMethod(mat, mult, x, y);
2592     PetscCall(VecLockReadPop(x));
2593   } else {
2594     Vec w;
2595     PetscCall(VecDuplicate(x, &w));
2596     PetscCall(VecCopy(x, w));
2597     PetscCall(VecConjugate(w));
2598     PetscCall(MatMultTranspose(mat, w, y));
2599     PetscCall(VecDestroy(&w));
2600     PetscCall(VecConjugate(y));
2601   }
2602   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2603 #else
2604   PetscCall(MatMultTranspose(mat, x, y));
2605 #endif
2606   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2607   PetscFunctionReturn(0);
2608 }
2609 
2610 /*@
2611     MatMultAdd -  Computes v3 = v2 + A * v1.
2612 
2613     Neighbor-wise Collective on Mat
2614 
2615     Input Parameters:
2616 +   mat - the matrix
2617 -   v1, v2 - the vectors
2618 
2619     Output Parameters:
2620 .   v3 - the result
2621 
2622     Notes:
2623     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2624     call MatMultAdd(A,v1,v2,v1).
2625 
2626     Level: beginner
2627 
2628 .seealso: `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2629 @*/
2630 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) {
2631   PetscFunctionBegin;
2632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2633   PetscValidType(mat, 1);
2634   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2635   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2636   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2637 
2638   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2639   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2640   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);
2641   /* 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);
2642      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); */
2643   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);
2644   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);
2645   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2646   MatCheckPreallocated(mat, 1);
2647 
2648   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2649   PetscCall(VecLockReadPush(v1));
2650   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2651   PetscCall(VecLockReadPop(v1));
2652   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2653   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2654   PetscFunctionReturn(0);
2655 }
2656 
2657 /*@
2658    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2659 
2660    Neighbor-wise Collective on Mat
2661 
2662    Input Parameters:
2663 +  mat - the matrix
2664 -  v1, v2 - the vectors
2665 
2666    Output Parameters:
2667 .  v3 - the result
2668 
2669    Notes:
2670    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2671    call MatMultTransposeAdd(A,v1,v2,v1).
2672 
2673    Level: beginner
2674 
2675 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2676 @*/
2677 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) {
2678   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2679 
2680   PetscFunctionBegin;
2681   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2682   PetscValidType(mat, 1);
2683   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2684   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2685   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2686 
2687   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2688   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2689   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);
2690   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);
2691   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);
2692   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2693   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2694   MatCheckPreallocated(mat, 1);
2695 
2696   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2697   PetscCall(VecLockReadPush(v1));
2698   PetscCall((*op)(mat, v1, v2, v3));
2699   PetscCall(VecLockReadPop(v1));
2700   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2701   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2702   PetscFunctionReturn(0);
2703 }
2704 
2705 /*@
2706    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2707 
2708    Neighbor-wise Collective on Mat
2709 
2710    Input Parameters:
2711 +  mat - the matrix
2712 -  v1, v2 - the vectors
2713 
2714    Output Parameters:
2715 .  v3 - the result
2716 
2717    Notes:
2718    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2719    call MatMultHermitianTransposeAdd(A,v1,v2,v1).
2720 
2721    Level: beginner
2722 
2723 .seealso: `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2724 @*/
2725 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) {
2726   PetscFunctionBegin;
2727   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2728   PetscValidType(mat, 1);
2729   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2730   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2731   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2732 
2733   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2734   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2735   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2736   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);
2737   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);
2738   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);
2739   MatCheckPreallocated(mat, 1);
2740 
2741   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2742   PetscCall(VecLockReadPush(v1));
2743   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2744   else {
2745     Vec w, z;
2746     PetscCall(VecDuplicate(v1, &w));
2747     PetscCall(VecCopy(v1, w));
2748     PetscCall(VecConjugate(w));
2749     PetscCall(VecDuplicate(v3, &z));
2750     PetscCall(MatMultTranspose(mat, w, z));
2751     PetscCall(VecDestroy(&w));
2752     PetscCall(VecConjugate(z));
2753     if (v2 != v3) {
2754       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2755     } else {
2756       PetscCall(VecAXPY(v3, 1.0, z));
2757     }
2758     PetscCall(VecDestroy(&z));
2759   }
2760   PetscCall(VecLockReadPop(v1));
2761   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2762   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2763   PetscFunctionReturn(0);
2764 }
2765 
2766 /*@C
2767    MatGetFactorType - gets the type of factorization it is
2768 
2769    Not Collective
2770 
2771    Input Parameters:
2772 .  mat - the matrix
2773 
2774    Output Parameters:
2775 .  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2776 
2777    Level: intermediate
2778 
2779 .seealso: `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`
2780 @*/
2781 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) {
2782   PetscFunctionBegin;
2783   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2784   PetscValidType(mat, 1);
2785   PetscValidPointer(t, 2);
2786   *t = mat->factortype;
2787   PetscFunctionReturn(0);
2788 }
2789 
2790 /*@C
2791    MatSetFactorType - sets the type of factorization it is
2792 
2793    Logically Collective on Mat
2794 
2795    Input Parameters:
2796 +  mat - the matrix
2797 -  t - the type, one of MAT_FACTOR_NONE, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ILU, MAT_FACTOR_ICC,MAT_FACTOR_ILUDT
2798 
2799    Level: intermediate
2800 
2801 .seealso: `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`
2802 @*/
2803 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) {
2804   PetscFunctionBegin;
2805   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2806   PetscValidType(mat, 1);
2807   mat->factortype = t;
2808   PetscFunctionReturn(0);
2809 }
2810 
2811 /* ------------------------------------------------------------*/
2812 /*@C
2813    MatGetInfo - Returns information about matrix storage (number of
2814    nonzeros, memory, etc.).
2815 
2816    Collective on Mat if MAT_GLOBAL_MAX or MAT_GLOBAL_SUM is used as the flag
2817 
2818    Input Parameter:
2819 .  mat - the matrix
2820 
2821    Output Parameters:
2822 +  flag - flag indicating the type of parameters to be returned
2823    (MAT_LOCAL - local matrix, MAT_GLOBAL_MAX - maximum over all processors,
2824    MAT_GLOBAL_SUM - sum over all processors)
2825 -  info - matrix information context
2826 
2827    Notes:
2828    The MatInfo context contains a variety of matrix data, including
2829    number of nonzeros allocated and used, number of mallocs during
2830    matrix assembly, etc.  Additional information for factored matrices
2831    is provided (such as the fill ratio, number of mallocs during
2832    factorization, etc.).  Much of this info is printed to PETSC_STDOUT
2833    when using the runtime options
2834 $       -info -mat_view ::ascii_info
2835 
2836    Example for C/C++ Users:
2837    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2838    data within the MatInfo context.  For example,
2839 .vb
2840       MatInfo info;
2841       Mat     A;
2842       double  mal, nz_a, nz_u;
2843 
2844       MatGetInfo(A,MAT_LOCAL,&info);
2845       mal  = info.mallocs;
2846       nz_a = info.nz_allocated;
2847 .ve
2848 
2849    Example for Fortran Users:
2850    Fortran users should declare info as a double precision
2851    array of dimension MAT_INFO_SIZE, and then extract the parameters
2852    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2853    a complete list of parameter names.
2854 .vb
2855       double  precision info(MAT_INFO_SIZE)
2856       double  precision mal, nz_a
2857       Mat     A
2858       integer ierr
2859 
2860       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2861       mal = info(MAT_INFO_MALLOCS)
2862       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2863 .ve
2864 
2865     Level: intermediate
2866 
2867     Developer Note: fortran interface is not autogenerated as the f90
2868     interface definition cannot be generated correctly [due to MatInfo]
2869 
2870 .seealso: `MatStashGetInfo()`
2871 
2872 @*/
2873 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) {
2874   PetscFunctionBegin;
2875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2876   PetscValidType(mat, 1);
2877   PetscValidPointer(info, 3);
2878   MatCheckPreallocated(mat, 1);
2879   PetscUseTypeMethod(mat, getinfo, flag, info);
2880   PetscFunctionReturn(0);
2881 }
2882 
2883 /*
2884    This is used by external packages where it is not easy to get the info from the actual
2885    matrix factorization.
2886 */
2887 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) {
2888   PetscFunctionBegin;
2889   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2890   PetscFunctionReturn(0);
2891 }
2892 
2893 /* ----------------------------------------------------------*/
2894 
2895 /*@C
2896    MatLUFactor - Performs in-place LU factorization of matrix.
2897 
2898    Collective on Mat
2899 
2900    Input Parameters:
2901 +  mat - the matrix
2902 .  row - row permutation
2903 .  col - column permutation
2904 -  info - options for factorization, includes
2905 $          fill - expected fill as ratio of original fill.
2906 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2907 $                   Run with the option -info to determine an optimal value to use
2908 
2909    Notes:
2910    Most users should employ the simplified KSP interface for linear solvers
2911    instead of working directly with matrix algebra routines such as this.
2912    See, e.g., KSPCreate().
2913 
2914    This changes the state of the matrix to a factored matrix; it cannot be used
2915    for example with MatSetValues() unless one first calls MatSetUnfactored().
2916 
2917    Level: developer
2918 
2919 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2920           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2921 
2922     Developer Note: fortran interface is not autogenerated as the f90
2923     interface definition cannot be generated correctly [due to MatFactorInfo]
2924 
2925 @*/
2926 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) {
2927   MatFactorInfo tinfo;
2928 
2929   PetscFunctionBegin;
2930   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2931   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
2932   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
2933   if (info) PetscValidPointer(info, 4);
2934   PetscValidType(mat, 1);
2935   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2936   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2937   MatCheckPreallocated(mat, 1);
2938   if (!info) {
2939     PetscCall(MatFactorInfoInitialize(&tinfo));
2940     info = &tinfo;
2941   }
2942 
2943   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
2944   PetscUseTypeMethod(mat, lufactor, row, col, info);
2945   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
2946   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
2947   PetscFunctionReturn(0);
2948 }
2949 
2950 /*@C
2951    MatILUFactor - Performs in-place ILU factorization of matrix.
2952 
2953    Collective on Mat
2954 
2955    Input Parameters:
2956 +  mat - the matrix
2957 .  row - row permutation
2958 .  col - column permutation
2959 -  info - structure containing
2960 $      levels - number of levels of fill.
2961 $      expected fill - as ratio of original fill.
2962 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
2963                 missing diagonal entries)
2964 
2965    Notes:
2966    Probably really in-place only when level of fill is zero, otherwise allocates
2967    new space to store factored matrix and deletes previous memory.
2968 
2969    Most users should employ the simplified KSP interface for linear solvers
2970    instead of working directly with matrix algebra routines such as this.
2971    See, e.g., KSPCreate().
2972 
2973    Level: developer
2974 
2975 .seealso: `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
2976 
2977     Developer Note: fortran interface is not autogenerated as the f90
2978     interface definition cannot be generated correctly [due to MatFactorInfo]
2979 
2980 @*/
2981 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) {
2982   PetscFunctionBegin;
2983   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2984   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
2985   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
2986   PetscValidPointer(info, 4);
2987   PetscValidType(mat, 1);
2988   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
2989   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2990   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2991   MatCheckPreallocated(mat, 1);
2992 
2993   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
2994   PetscUseTypeMethod(mat, ilufactor, row, col, info);
2995   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
2996   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
2997   PetscFunctionReturn(0);
2998 }
2999 
3000 /*@C
3001    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3002    Call this routine before calling MatLUFactorNumeric().
3003 
3004    Collective on Mat
3005 
3006    Input Parameters:
3007 +  fact - the factor matrix obtained with MatGetFactor()
3008 .  mat - the matrix
3009 .  row, col - row and column permutations
3010 -  info - options for factorization, includes
3011 $          fill - expected fill as ratio of original fill.
3012 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3013 $                   Run with the option -info to determine an optimal value to use
3014 
3015    Notes:
3016     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
3017 
3018    Most users should employ the simplified KSP interface for linear solvers
3019    instead of working directly with matrix algebra routines such as this.
3020    See, e.g., KSPCreate().
3021 
3022    Level: developer
3023 
3024 .seealso: `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3025 
3026     Developer Note: fortran interface is not autogenerated as the f90
3027     interface definition cannot be generated correctly [due to MatFactorInfo]
3028 
3029 @*/
3030 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) {
3031   MatFactorInfo tinfo;
3032 
3033   PetscFunctionBegin;
3034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3035   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3036   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3037   if (info) PetscValidPointer(info, 5);
3038   PetscValidType(mat, 2);
3039   PetscValidPointer(fact, 1);
3040   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3041   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3042   if (!(fact)->ops->lufactorsymbolic) {
3043     MatSolverType stype;
3044     PetscCall(MatFactorGetSolverType(fact, &stype));
3045     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3046   }
3047   MatCheckPreallocated(mat, 2);
3048   if (!info) {
3049     PetscCall(MatFactorInfoInitialize(&tinfo));
3050     info = &tinfo;
3051   }
3052 
3053   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3054   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3055   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3056   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3057   PetscFunctionReturn(0);
3058 }
3059 
3060 /*@C
3061    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3062    Call this routine after first calling MatLUFactorSymbolic().
3063 
3064    Collective on Mat
3065 
3066    Input Parameters:
3067 +  fact - the factor matrix obtained with MatGetFactor()
3068 .  mat - the matrix
3069 -  info - options for factorization
3070 
3071    Notes:
3072    See MatLUFactor() for in-place factorization.  See
3073    MatCholeskyFactorNumeric() for the symmetric, positive definite case.
3074 
3075    Most users should employ the simplified KSP interface for linear solvers
3076    instead of working directly with matrix algebra routines such as this.
3077    See, e.g., KSPCreate().
3078 
3079    Level: developer
3080 
3081 .seealso: `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3082 
3083     Developer Note: fortran interface is not autogenerated as the f90
3084     interface definition cannot be generated correctly [due to MatFactorInfo]
3085 
3086 @*/
3087 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) {
3088   MatFactorInfo tinfo;
3089 
3090   PetscFunctionBegin;
3091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3092   PetscValidType(mat, 2);
3093   PetscValidPointer(fact, 1);
3094   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3095   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3096   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,
3097              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3098 
3099   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3100   MatCheckPreallocated(mat, 2);
3101   if (!info) {
3102     PetscCall(MatFactorInfoInitialize(&tinfo));
3103     info = &tinfo;
3104   }
3105 
3106   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3107   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3108   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3109   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3110   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3111   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3112   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3113   PetscFunctionReturn(0);
3114 }
3115 
3116 /*@C
3117    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3118    symmetric matrix.
3119 
3120    Collective on Mat
3121 
3122    Input Parameters:
3123 +  mat - the matrix
3124 .  perm - row and column permutations
3125 -  f - expected fill as ratio of original fill
3126 
3127    Notes:
3128    See MatLUFactor() for the nonsymmetric case.  See also
3129    MatCholeskyFactorSymbolic(), and MatCholeskyFactorNumeric().
3130 
3131    Most users should employ the simplified KSP interface for linear solvers
3132    instead of working directly with matrix algebra routines such as this.
3133    See, e.g., KSPCreate().
3134 
3135    Level: developer
3136 
3137 .seealso: `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3138           `MatGetOrdering()`
3139 
3140     Developer Note: fortran interface is not autogenerated as the f90
3141     interface definition cannot be generated correctly [due to MatFactorInfo]
3142 
3143 @*/
3144 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) {
3145   MatFactorInfo tinfo;
3146 
3147   PetscFunctionBegin;
3148   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3149   PetscValidType(mat, 1);
3150   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3151   if (info) PetscValidPointer(info, 3);
3152   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3153   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3154   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3155   MatCheckPreallocated(mat, 1);
3156   if (!info) {
3157     PetscCall(MatFactorInfoInitialize(&tinfo));
3158     info = &tinfo;
3159   }
3160 
3161   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3162   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3163   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3164   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3165   PetscFunctionReturn(0);
3166 }
3167 
3168 /*@C
3169    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3170    of a symmetric matrix.
3171 
3172    Collective on Mat
3173 
3174    Input Parameters:
3175 +  fact - the factor matrix obtained with MatGetFactor()
3176 .  mat - the matrix
3177 .  perm - row and column permutations
3178 -  info - options for factorization, includes
3179 $          fill - expected fill as ratio of original fill.
3180 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3181 $                   Run with the option -info to determine an optimal value to use
3182 
3183    Notes:
3184    See MatLUFactorSymbolic() for the nonsymmetric case.  See also
3185    MatCholeskyFactor() and MatCholeskyFactorNumeric().
3186 
3187    Most users should employ the simplified KSP interface for linear solvers
3188    instead of working directly with matrix algebra routines such as this.
3189    See, e.g., KSPCreate().
3190 
3191    Level: developer
3192 
3193 .seealso: `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3194           `MatGetOrdering()`
3195 
3196     Developer Note: fortran interface is not autogenerated as the f90
3197     interface definition cannot be generated correctly [due to MatFactorInfo]
3198 
3199 @*/
3200 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) {
3201   MatFactorInfo tinfo;
3202 
3203   PetscFunctionBegin;
3204   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3205   PetscValidType(mat, 2);
3206   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3207   if (info) PetscValidPointer(info, 4);
3208   PetscValidPointer(fact, 1);
3209   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3210   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3211   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3212   if (!(fact)->ops->choleskyfactorsymbolic) {
3213     MatSolverType stype;
3214     PetscCall(MatFactorGetSolverType(fact, &stype));
3215     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3216   }
3217   MatCheckPreallocated(mat, 2);
3218   if (!info) {
3219     PetscCall(MatFactorInfoInitialize(&tinfo));
3220     info = &tinfo;
3221   }
3222 
3223   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3224   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3225   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3226   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3227   PetscFunctionReturn(0);
3228 }
3229 
3230 /*@C
3231    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3232    of a symmetric matrix. Call this routine after first calling
3233    MatCholeskyFactorSymbolic().
3234 
3235    Collective on Mat
3236 
3237    Input Parameters:
3238 +  fact - the factor matrix obtained with MatGetFactor()
3239 .  mat - the initial matrix
3240 .  info - options for factorization
3241 -  fact - the symbolic factor of mat
3242 
3243    Notes:
3244    Most users should employ the simplified KSP interface for linear solvers
3245    instead of working directly with matrix algebra routines such as this.
3246    See, e.g., KSPCreate().
3247 
3248    Level: developer
3249 
3250 .seealso: `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3251 
3252     Developer Note: fortran interface is not autogenerated as the f90
3253     interface definition cannot be generated correctly [due to MatFactorInfo]
3254 
3255 @*/
3256 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) {
3257   MatFactorInfo tinfo;
3258 
3259   PetscFunctionBegin;
3260   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3261   PetscValidType(mat, 2);
3262   PetscValidPointer(fact, 1);
3263   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3264   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3265   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3266   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,
3267              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3268   MatCheckPreallocated(mat, 2);
3269   if (!info) {
3270     PetscCall(MatFactorInfoInitialize(&tinfo));
3271     info = &tinfo;
3272   }
3273 
3274   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3275   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3276   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3277   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3278   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3279   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3280   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3281   PetscFunctionReturn(0);
3282 }
3283 
3284 /*@
3285    MatQRFactor - Performs in-place QR factorization of matrix.
3286 
3287    Collective on Mat
3288 
3289    Input Parameters:
3290 +  mat - the matrix
3291 .  col - column permutation
3292 -  info - options for factorization, includes
3293 $          fill - expected fill as ratio of original fill.
3294 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3295 $                   Run with the option -info to determine an optimal value to use
3296 
3297    Notes:
3298    Most users should employ the simplified KSP interface for linear solvers
3299    instead of working directly with matrix algebra routines such as this.
3300    See, e.g., KSPCreate().
3301 
3302    This changes the state of the matrix to a factored matrix; it cannot be used
3303    for example with MatSetValues() unless one first calls MatSetUnfactored().
3304 
3305    Level: developer
3306 
3307 .seealso: `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3308           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3309 
3310     Developer Note: fortran interface is not autogenerated as the f90
3311     interface definition cannot be generated correctly [due to MatFactorInfo]
3312 
3313 @*/
3314 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) {
3315   PetscFunctionBegin;
3316   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3317   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3318   if (info) PetscValidPointer(info, 3);
3319   PetscValidType(mat, 1);
3320   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3321   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3322   MatCheckPreallocated(mat, 1);
3323   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3324   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3325   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3326   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3327   PetscFunctionReturn(0);
3328 }
3329 
3330 /*@
3331    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3332    Call this routine before calling MatQRFactorNumeric().
3333 
3334    Collective on Mat
3335 
3336    Input Parameters:
3337 +  fact - the factor matrix obtained with MatGetFactor()
3338 .  mat - the matrix
3339 .  col - column permutation
3340 -  info - options for factorization, includes
3341 $          fill - expected fill as ratio of original fill.
3342 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3343 $                   Run with the option -info to determine an optimal value to use
3344 
3345    Most users should employ the simplified KSP interface for linear solvers
3346    instead of working directly with matrix algebra routines such as this.
3347    See, e.g., KSPCreate().
3348 
3349    Level: developer
3350 
3351 .seealso: `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3352 
3353     Developer Note: fortran interface is not autogenerated as the f90
3354     interface definition cannot be generated correctly [due to MatFactorInfo]
3355 
3356 @*/
3357 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) {
3358   MatFactorInfo tinfo;
3359 
3360   PetscFunctionBegin;
3361   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3362   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3363   if (info) PetscValidPointer(info, 4);
3364   PetscValidType(mat, 2);
3365   PetscValidPointer(fact, 1);
3366   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3367   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3368   MatCheckPreallocated(mat, 2);
3369   if (!info) {
3370     PetscCall(MatFactorInfoInitialize(&tinfo));
3371     info = &tinfo;
3372   }
3373 
3374   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3375   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3376   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3377   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3378   PetscFunctionReturn(0);
3379 }
3380 
3381 /*@
3382    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3383    Call this routine after first calling MatQRFactorSymbolic().
3384 
3385    Collective on Mat
3386 
3387    Input Parameters:
3388 +  fact - the factor matrix obtained with MatGetFactor()
3389 .  mat - the matrix
3390 -  info - options for factorization
3391 
3392    Notes:
3393    See MatQRFactor() for in-place factorization.
3394 
3395    Most users should employ the simplified KSP interface for linear solvers
3396    instead of working directly with matrix algebra routines such as this.
3397    See, e.g., KSPCreate().
3398 
3399    Level: developer
3400 
3401 .seealso: `MatQRFactorSymbolic()`, `MatLUFactor()`
3402 
3403     Developer Note: fortran interface is not autogenerated as the f90
3404     interface definition cannot be generated correctly [due to MatFactorInfo]
3405 
3406 @*/
3407 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) {
3408   MatFactorInfo tinfo;
3409 
3410   PetscFunctionBegin;
3411   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3412   PetscValidType(mat, 2);
3413   PetscValidPointer(fact, 1);
3414   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3415   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3416   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,
3417              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3418 
3419   MatCheckPreallocated(mat, 2);
3420   if (!info) {
3421     PetscCall(MatFactorInfoInitialize(&tinfo));
3422     info = &tinfo;
3423   }
3424 
3425   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3426   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3427   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3428   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3429   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3430   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3431   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3432   PetscFunctionReturn(0);
3433 }
3434 
3435 /* ----------------------------------------------------------------*/
3436 /*@
3437    MatSolve - Solves A x = b, given a factored matrix.
3438 
3439    Neighbor-wise Collective on Mat
3440 
3441    Input Parameters:
3442 +  mat - the factored matrix
3443 -  b - the right-hand-side vector
3444 
3445    Output Parameter:
3446 .  x - the result vector
3447 
3448    Notes:
3449    The vectors b and x cannot be the same.  I.e., one cannot
3450    call MatSolve(A,x,x).
3451 
3452    Notes:
3453    Most users should employ the simplified KSP interface for linear solvers
3454    instead of working directly with matrix algebra routines such as this.
3455    See, e.g., KSPCreate().
3456 
3457    Level: developer
3458 
3459 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3460 @*/
3461 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) {
3462   PetscFunctionBegin;
3463   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3464   PetscValidType(mat, 1);
3465   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3466   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3467   PetscCheckSameComm(mat, 1, b, 2);
3468   PetscCheckSameComm(mat, 1, x, 3);
3469   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3470   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);
3471   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);
3472   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);
3473   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3474   MatCheckPreallocated(mat, 1);
3475 
3476   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3477   if (mat->factorerrortype) {
3478     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3479     PetscCall(VecSetInf(x));
3480   } else PetscUseTypeMethod(mat, solve, b, x);
3481   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3482   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3483   PetscFunctionReturn(0);
3484 }
3485 
3486 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) {
3487   Vec      b, x;
3488   PetscInt N, i;
3489   PetscErrorCode (*f)(Mat, Vec, Vec);
3490   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3491 
3492   PetscFunctionBegin;
3493   if (A->factorerrortype) {
3494     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3495     PetscCall(MatSetInf(X));
3496     PetscFunctionReturn(0);
3497   }
3498   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3499   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3500   PetscCall(MatBoundToCPU(A, &Abound));
3501   if (!Abound) {
3502     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3503     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3504   }
3505   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3506   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3507   PetscCall(MatGetSize(B, NULL, &N));
3508   for (i = 0; i < N; i++) {
3509     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3510     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3511     PetscCall((*f)(A, b, x));
3512     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3513     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3514   }
3515   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3516   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3517   PetscFunctionReturn(0);
3518 }
3519 
3520 /*@
3521    MatMatSolve - Solves A X = B, given a factored matrix.
3522 
3523    Neighbor-wise Collective on Mat
3524 
3525    Input Parameters:
3526 +  A - the factored matrix
3527 -  B - the right-hand-side matrix MATDENSE (or sparse -- when using MUMPS)
3528 
3529    Output Parameter:
3530 .  X - the result matrix (dense matrix)
3531 
3532    Notes:
3533    If B is a MATDENSE matrix then one can call MatMatSolve(A,B,B) except with MKL_CPARDISO;
3534    otherwise, B and X cannot be the same.
3535 
3536    Notes:
3537    Most users should usually employ the simplified KSP interface for linear solvers
3538    instead of working directly with matrix algebra routines such as this.
3539    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3540    at a time.
3541 
3542    Level: developer
3543 
3544 .seealso: `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3545 @*/
3546 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) {
3547   PetscFunctionBegin;
3548   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3549   PetscValidType(A, 1);
3550   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3551   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3552   PetscCheckSameComm(A, 1, B, 2);
3553   PetscCheckSameComm(A, 1, X, 3);
3554   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);
3555   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);
3556   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");
3557   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3558   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3559   MatCheckPreallocated(A, 1);
3560 
3561   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3562   if (!A->ops->matsolve) {
3563     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3564     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3565   } else PetscUseTypeMethod(A, matsolve, B, X);
3566   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3567   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3568   PetscFunctionReturn(0);
3569 }
3570 
3571 /*@
3572    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3573 
3574    Neighbor-wise Collective on Mat
3575 
3576    Input Parameters:
3577 +  A - the factored matrix
3578 -  B - the right-hand-side matrix  (dense matrix)
3579 
3580    Output Parameter:
3581 .  X - the result matrix (dense matrix)
3582 
3583    Notes:
3584    The matrices B and X cannot be the same.  I.e., one cannot
3585    call MatMatSolveTranspose(A,X,X).
3586 
3587    Notes:
3588    Most users should usually employ the simplified KSP interface for linear solvers
3589    instead of working directly with matrix algebra routines such as this.
3590    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3591    at a time.
3592 
3593    When using SuperLU_Dist or MUMPS as a parallel solver, PETSc will use their functionality to solve multiple right hand sides simultaneously.
3594 
3595    Level: developer
3596 
3597 .seealso: `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3598 @*/
3599 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) {
3600   PetscFunctionBegin;
3601   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3602   PetscValidType(A, 1);
3603   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3604   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3605   PetscCheckSameComm(A, 1, B, 2);
3606   PetscCheckSameComm(A, 1, X, 3);
3607   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3608   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);
3609   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);
3610   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);
3611   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");
3612   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3613   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3614   MatCheckPreallocated(A, 1);
3615 
3616   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3617   if (!A->ops->matsolvetranspose) {
3618     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3619     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3620   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3621   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3622   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3623   PetscFunctionReturn(0);
3624 }
3625 
3626 /*@
3627    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3628 
3629    Neighbor-wise Collective on Mat
3630 
3631    Input Parameters:
3632 +  A - the factored matrix
3633 -  Bt - the transpose of right-hand-side matrix
3634 
3635    Output Parameter:
3636 .  X - the result matrix (dense matrix)
3637 
3638    Notes:
3639    Most users should usually employ the simplified KSP interface for linear solvers
3640    instead of working directly with matrix algebra routines such as this.
3641    See, e.g., KSPCreate(). However KSP can only solve for one vector (column of X)
3642    at a time.
3643 
3644    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 format on the host processor and call MatMatTransposeSolve() to implement MUMPS' MatMatSolve().
3645 
3646    Level: developer
3647 
3648 .seealso: `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3649 @*/
3650 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) {
3651   PetscFunctionBegin;
3652   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3653   PetscValidType(A, 1);
3654   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3655   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3656   PetscCheckSameComm(A, 1, Bt, 2);
3657   PetscCheckSameComm(A, 1, X, 3);
3658 
3659   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3660   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);
3661   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);
3662   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");
3663   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3664   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3665   MatCheckPreallocated(A, 1);
3666 
3667   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3668   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3669   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3670   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3671   PetscFunctionReturn(0);
3672 }
3673 
3674 /*@
3675    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3676                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3677 
3678    Neighbor-wise Collective on Mat
3679 
3680    Input Parameters:
3681 +  mat - the factored matrix
3682 -  b - the right-hand-side vector
3683 
3684    Output Parameter:
3685 .  x - the result vector
3686 
3687    Notes:
3688    MatSolve() should be used for most applications, as it performs
3689    a forward solve followed by a backward solve.
3690 
3691    The vectors b and x cannot be the same,  i.e., one cannot
3692    call MatForwardSolve(A,x,x).
3693 
3694    For matrix in seqsbaij format with block size larger than 1,
3695    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3696    MatForwardSolve() solves U^T*D y = b, and
3697    MatBackwardSolve() solves U x = y.
3698    Thus they do not provide a symmetric preconditioner.
3699 
3700    Most users should employ the simplified KSP interface for linear solvers
3701    instead of working directly with matrix algebra routines such as this.
3702    See, e.g., KSPCreate().
3703 
3704    Level: developer
3705 
3706 .seealso: `MatSolve()`, `MatBackwardSolve()`
3707 @*/
3708 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) {
3709   PetscFunctionBegin;
3710   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3711   PetscValidType(mat, 1);
3712   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3713   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3714   PetscCheckSameComm(mat, 1, b, 2);
3715   PetscCheckSameComm(mat, 1, x, 3);
3716   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3717   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);
3718   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);
3719   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);
3720   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3721   MatCheckPreallocated(mat, 1);
3722 
3723   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3724   PetscUseTypeMethod(mat, forwardsolve, b, x);
3725   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3726   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3727   PetscFunctionReturn(0);
3728 }
3729 
3730 /*@
3731    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3732                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3733 
3734    Neighbor-wise Collective on Mat
3735 
3736    Input Parameters:
3737 +  mat - the factored matrix
3738 -  b - the right-hand-side vector
3739 
3740    Output Parameter:
3741 .  x - the result vector
3742 
3743    Notes:
3744    MatSolve() should be used for most applications, as it performs
3745    a forward solve followed by a backward solve.
3746 
3747    The vectors b and x cannot be the same.  I.e., one cannot
3748    call MatBackwardSolve(A,x,x).
3749 
3750    For matrix in seqsbaij format with block size larger than 1,
3751    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3752    MatForwardSolve() solves U^T*D y = b, and
3753    MatBackwardSolve() solves U x = y.
3754    Thus they do not provide a symmetric preconditioner.
3755 
3756    Most users should employ the simplified KSP interface for linear solvers
3757    instead of working directly with matrix algebra routines such as this.
3758    See, e.g., KSPCreate().
3759 
3760    Level: developer
3761 
3762 .seealso: `MatSolve()`, `MatForwardSolve()`
3763 @*/
3764 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) {
3765   PetscFunctionBegin;
3766   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3767   PetscValidType(mat, 1);
3768   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3769   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3770   PetscCheckSameComm(mat, 1, b, 2);
3771   PetscCheckSameComm(mat, 1, x, 3);
3772   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3773   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);
3774   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);
3775   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);
3776   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3777   MatCheckPreallocated(mat, 1);
3778 
3779   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3780   PetscUseTypeMethod(mat, backwardsolve, b, x);
3781   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3782   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3783   PetscFunctionReturn(0);
3784 }
3785 
3786 /*@
3787    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3788 
3789    Neighbor-wise Collective on Mat
3790 
3791    Input Parameters:
3792 +  mat - the factored matrix
3793 .  b - the right-hand-side vector
3794 -  y - the vector to be added to
3795 
3796    Output Parameter:
3797 .  x - the result vector
3798 
3799    Notes:
3800    The vectors b and x cannot be the same.  I.e., one cannot
3801    call MatSolveAdd(A,x,y,x).
3802 
3803    Most users should employ the simplified KSP interface for linear solvers
3804    instead of working directly with matrix algebra routines such as this.
3805    See, e.g., KSPCreate().
3806 
3807    Level: developer
3808 
3809 .seealso: `MatSolve()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3810 @*/
3811 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) {
3812   PetscScalar one = 1.0;
3813   Vec         tmp;
3814 
3815   PetscFunctionBegin;
3816   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3817   PetscValidType(mat, 1);
3818   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3819   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3820   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3821   PetscCheckSameComm(mat, 1, b, 2);
3822   PetscCheckSameComm(mat, 1, y, 3);
3823   PetscCheckSameComm(mat, 1, x, 4);
3824   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3825   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);
3826   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);
3827   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);
3828   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);
3829   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);
3830   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3831   MatCheckPreallocated(mat, 1);
3832 
3833   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3834   if (mat->factorerrortype) {
3835     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3836     PetscCall(VecSetInf(x));
3837   } else if (mat->ops->solveadd) {
3838     PetscUseTypeMethod(mat, solveadd, b, y, x);
3839   } else {
3840     /* do the solve then the add manually */
3841     if (x != y) {
3842       PetscCall(MatSolve(mat, b, x));
3843       PetscCall(VecAXPY(x, one, y));
3844     } else {
3845       PetscCall(VecDuplicate(x, &tmp));
3846       PetscCall(PetscLogObjectParent((PetscObject)mat, (PetscObject)tmp));
3847       PetscCall(VecCopy(x, tmp));
3848       PetscCall(MatSolve(mat, b, x));
3849       PetscCall(VecAXPY(x, one, tmp));
3850       PetscCall(VecDestroy(&tmp));
3851     }
3852   }
3853   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3854   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3855   PetscFunctionReturn(0);
3856 }
3857 
3858 /*@
3859    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3860 
3861    Neighbor-wise Collective on Mat
3862 
3863    Input Parameters:
3864 +  mat - the factored matrix
3865 -  b - the right-hand-side vector
3866 
3867    Output Parameter:
3868 .  x - the result vector
3869 
3870    Notes:
3871    The vectors b and x cannot be the same.  I.e., one cannot
3872    call MatSolveTranspose(A,x,x).
3873 
3874    Most users should employ the simplified KSP interface for linear solvers
3875    instead of working directly with matrix algebra routines such as this.
3876    See, e.g., KSPCreate().
3877 
3878    Level: developer
3879 
3880 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3881 @*/
3882 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) {
3883   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3884 
3885   PetscFunctionBegin;
3886   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3887   PetscValidType(mat, 1);
3888   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3889   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3890   PetscCheckSameComm(mat, 1, b, 2);
3891   PetscCheckSameComm(mat, 1, x, 3);
3892   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3893   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);
3894   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);
3895   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3896   MatCheckPreallocated(mat, 1);
3897   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3898   if (mat->factorerrortype) {
3899     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3900     PetscCall(VecSetInf(x));
3901   } else {
3902     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
3903     PetscCall((*f)(mat, b, x));
3904   }
3905   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
3906   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3907   PetscFunctionReturn(0);
3908 }
3909 
3910 /*@
3911    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3912                       factored matrix.
3913 
3914    Neighbor-wise Collective on Mat
3915 
3916    Input Parameters:
3917 +  mat - the factored matrix
3918 .  b - the right-hand-side vector
3919 -  y - the vector to be added to
3920 
3921    Output Parameter:
3922 .  x - the result vector
3923 
3924    Notes:
3925    The vectors b and x cannot be the same.  I.e., one cannot
3926    call MatSolveTransposeAdd(A,x,y,x).
3927 
3928    Most users should employ the simplified KSP interface for linear solvers
3929    instead of working directly with matrix algebra routines such as this.
3930    See, e.g., KSPCreate().
3931 
3932    Level: developer
3933 
3934 .seealso: `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3935 @*/
3936 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) {
3937   PetscScalar one = 1.0;
3938   Vec         tmp;
3939   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
3940 
3941   PetscFunctionBegin;
3942   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3943   PetscValidType(mat, 1);
3944   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3945   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3946   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3947   PetscCheckSameComm(mat, 1, b, 2);
3948   PetscCheckSameComm(mat, 1, y, 3);
3949   PetscCheckSameComm(mat, 1, x, 4);
3950   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3951   PetscCheck(mat->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);
3952   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);
3953   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);
3954   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);
3955   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3956   MatCheckPreallocated(mat, 1);
3957 
3958   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
3959   if (mat->factorerrortype) {
3960     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3961     PetscCall(VecSetInf(x));
3962   } else if (f) {
3963     PetscCall((*f)(mat, b, y, x));
3964   } else {
3965     /* do the solve then the add manually */
3966     if (x != y) {
3967       PetscCall(MatSolveTranspose(mat, b, x));
3968       PetscCall(VecAXPY(x, one, y));
3969     } else {
3970       PetscCall(VecDuplicate(x, &tmp));
3971       PetscCall(PetscLogObjectParent((PetscObject)mat, (PetscObject)tmp));
3972       PetscCall(VecCopy(x, tmp));
3973       PetscCall(MatSolveTranspose(mat, b, x));
3974       PetscCall(VecAXPY(x, one, tmp));
3975       PetscCall(VecDestroy(&tmp));
3976     }
3977   }
3978   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
3979   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3980   PetscFunctionReturn(0);
3981 }
3982 /* ----------------------------------------------------------------*/
3983 
3984 /*@
3985    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
3986 
3987    Neighbor-wise Collective on Mat
3988 
3989    Input Parameters:
3990 +  mat - the matrix
3991 .  b - the right hand side
3992 .  omega - the relaxation factor
3993 .  flag - flag indicating the type of SOR (see below)
3994 .  shift -  diagonal shift
3995 .  its - the number of iterations
3996 -  lits - the number of local iterations
3997 
3998    Output Parameter:
3999 .  x - the solution (can contain an initial guess, use option SOR_ZERO_INITIAL_GUESS to indicate no guess)
4000 
4001    SOR Flags:
4002 +     SOR_FORWARD_SWEEP - forward SOR
4003 .     SOR_BACKWARD_SWEEP - backward SOR
4004 .     SOR_SYMMETRIC_SWEEP - SSOR (symmetric SOR)
4005 .     SOR_LOCAL_FORWARD_SWEEP - local forward SOR
4006 .     SOR_LOCAL_BACKWARD_SWEEP - local forward SOR
4007 .     SOR_LOCAL_SYMMETRIC_SWEEP - local SSOR
4008 .     SOR_APPLY_UPPER, SOR_APPLY_LOWER - applies
4009          upper/lower triangular part of matrix to
4010          vector (with omega)
4011 -     SOR_ZERO_INITIAL_GUESS - zero initial guess
4012 
4013    Notes:
4014    SOR_LOCAL_FORWARD_SWEEP, SOR_LOCAL_BACKWARD_SWEEP, and
4015    SOR_LOCAL_SYMMETRIC_SWEEP perform separate independent smoothings
4016    on each processor.
4017 
4018    Application programmers will not generally use MatSOR() directly,
4019    but instead will employ the KSP/PC interface.
4020 
4021    Notes:
4022     for BAIJ, SBAIJ, and AIJ matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4023 
4024    Notes for Advanced Users:
4025    The flags are implemented as bitwise inclusive or operations.
4026    For example, use (SOR_ZERO_INITIAL_GUESS | SOR_SYMMETRIC_SWEEP)
4027    to specify a zero initial guess for SSOR.
4028 
4029    Most users should employ the simplified KSP interface for linear solvers
4030    instead of working directly with matrix algebra routines such as this.
4031    See, e.g., KSPCreate().
4032 
4033    Vectors x and b CANNOT be the same
4034 
4035    Developer Note: We should add block SOR support for AIJ matrices with block size set to great than one and no inodes
4036 
4037    Level: developer
4038 
4039 @*/
4040 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) {
4041   PetscFunctionBegin;
4042   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4043   PetscValidType(mat, 1);
4044   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4045   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4046   PetscCheckSameComm(mat, 1, b, 2);
4047   PetscCheckSameComm(mat, 1, x, 8);
4048   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4049   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4050   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);
4051   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);
4052   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);
4053   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4054   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4055   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4056 
4057   MatCheckPreallocated(mat, 1);
4058   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4059   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4060   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4061   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4062   PetscFunctionReturn(0);
4063 }
4064 
4065 /*
4066       Default matrix copy routine.
4067 */
4068 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) {
4069   PetscInt           i, rstart = 0, rend = 0, nz;
4070   const PetscInt    *cwork;
4071   const PetscScalar *vwork;
4072 
4073   PetscFunctionBegin;
4074   if (B->assembled) PetscCall(MatZeroEntries(B));
4075   if (str == SAME_NONZERO_PATTERN) {
4076     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4077     for (i = rstart; i < rend; i++) {
4078       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4079       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4080       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4081     }
4082   } else {
4083     PetscCall(MatAYPX(B, 0.0, A, str));
4084   }
4085   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4086   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4087   PetscFunctionReturn(0);
4088 }
4089 
4090 /*@
4091    MatCopy - Copies a matrix to another matrix.
4092 
4093    Collective on Mat
4094 
4095    Input Parameters:
4096 +  A - the matrix
4097 -  str - SAME_NONZERO_PATTERN or DIFFERENT_NONZERO_PATTERN
4098 
4099    Output Parameter:
4100 .  B - where the copy is put
4101 
4102    Notes:
4103    If you use SAME_NONZERO_PATTERN then the two matrices must have the same nonzero pattern or the routine will crash.
4104 
4105    MatCopy() copies the matrix entries of a matrix to another existing
4106    matrix (after first zeroing the second matrix).  A related routine is
4107    MatConvert(), which first creates a new matrix and then copies the data.
4108 
4109    Level: intermediate
4110 
4111 .seealso: `MatConvert()`, `MatDuplicate()`
4112 @*/
4113 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) {
4114   PetscInt i;
4115 
4116   PetscFunctionBegin;
4117   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4118   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4119   PetscValidType(A, 1);
4120   PetscValidType(B, 2);
4121   PetscCheckSameComm(A, 1, B, 2);
4122   MatCheckPreallocated(B, 2);
4123   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4124   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4125   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,
4126              A->cmap->N, B->cmap->N);
4127   MatCheckPreallocated(A, 1);
4128   if (A == B) PetscFunctionReturn(0);
4129 
4130   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4131   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4132   else PetscCall(MatCopy_Basic(A, B, str));
4133 
4134   B->stencil.dim = A->stencil.dim;
4135   B->stencil.noc = A->stencil.noc;
4136   for (i = 0; i <= A->stencil.dim; i++) {
4137     B->stencil.dims[i]   = A->stencil.dims[i];
4138     B->stencil.starts[i] = A->stencil.starts[i];
4139   }
4140 
4141   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4142   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4143   PetscFunctionReturn(0);
4144 }
4145 
4146 /*@C
4147    MatConvert - Converts a matrix to another matrix, either of the same
4148    or different type.
4149 
4150    Collective on Mat
4151 
4152    Input Parameters:
4153 +  mat - the matrix
4154 .  newtype - new matrix type.  Use MATSAME to create a new matrix of the
4155    same type as the original matrix.
4156 -  reuse - denotes if the destination matrix is to be created or reused.
4157    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
4158    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).
4159 
4160    Output Parameter:
4161 .  M - pointer to place new matrix
4162 
4163    Notes:
4164    MatConvert() first creates a new matrix and then copies the data from
4165    the first matrix.  A related routine is MatCopy(), which copies the matrix
4166    entries of one matrix to another already existing matrix context.
4167 
4168    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4169    the MPI communicator of the generated matrix is always the same as the communicator
4170    of the input matrix.
4171 
4172    Level: intermediate
4173 
4174 .seealso: `MatCopy()`, `MatDuplicate()`
4175 @*/
4176 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) {
4177   PetscBool  sametype, issame, flg;
4178   PetscBool3 issymmetric, ishermitian;
4179   char       convname[256], mtype[256];
4180   Mat        B;
4181 
4182   PetscFunctionBegin;
4183   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4184   PetscValidType(mat, 1);
4185   PetscValidPointer(M, 4);
4186   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4187   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4188   MatCheckPreallocated(mat, 1);
4189 
4190   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4191   if (flg) newtype = mtype;
4192 
4193   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4194   PetscCall(PetscStrcmp(newtype, "same", &issame));
4195   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4196   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");
4197 
4198   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4199     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4200     PetscFunctionReturn(0);
4201   }
4202 
4203   /* Cache Mat options because some converters use MatHeaderReplace  */
4204   issymmetric = mat->symmetric;
4205   ishermitian = mat->hermitian;
4206 
4207   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4208     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4209     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4210   } else {
4211     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4212     const char *prefix[3]                                 = {"seq", "mpi", ""};
4213     PetscInt    i;
4214     /*
4215        Order of precedence:
4216        0) See if newtype is a superclass of the current matrix.
4217        1) See if a specialized converter is known to the current matrix.
4218        2) See if a specialized converter is known to the desired matrix class.
4219        3) See if a good general converter is registered for the desired class
4220           (as of 6/27/03 only MATMPIADJ falls into this category).
4221        4) See if a good general converter is known for the current matrix.
4222        5) Use a really basic converter.
4223     */
4224 
4225     /* 0) See if newtype is a superclass of the current matrix.
4226           i.e mat is mpiaij and newtype is aij */
4227     for (i = 0; i < 2; i++) {
4228       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4229       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4230       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4231       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4232       if (flg) {
4233         if (reuse == MAT_INPLACE_MATRIX) {
4234           PetscCall(PetscInfo(mat, "Early return\n"));
4235           PetscFunctionReturn(0);
4236         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4237           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4238           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4239           PetscFunctionReturn(0);
4240         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4241           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4242           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4243           PetscFunctionReturn(0);
4244         }
4245       }
4246     }
4247     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4248     for (i = 0; i < 3; i++) {
4249       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4250       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4251       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4252       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4253       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4254       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4255       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4256       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4257       if (conv) goto foundconv;
4258     }
4259 
4260     /* 2)  See if a specialized converter is known to the desired matrix class. */
4261     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4262     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4263     PetscCall(MatSetType(B, newtype));
4264     for (i = 0; i < 3; i++) {
4265       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4266       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4267       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4268       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4269       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4270       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4271       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4272       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4273       if (conv) {
4274         PetscCall(MatDestroy(&B));
4275         goto foundconv;
4276       }
4277     }
4278 
4279     /* 3) See if a good general converter is registered for the desired class */
4280     conv = B->ops->convertfrom;
4281     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4282     PetscCall(MatDestroy(&B));
4283     if (conv) goto foundconv;
4284 
4285     /* 4) See if a good general converter is known for the current matrix */
4286     if (mat->ops->convert) conv = mat->ops->convert;
4287     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4288     if (conv) goto foundconv;
4289 
4290     /* 5) Use a really basic converter. */
4291     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4292     conv = MatConvert_Basic;
4293 
4294   foundconv:
4295     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4296     PetscCall((*conv)(mat, newtype, reuse, M));
4297     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4298       /* the block sizes must be same if the mappings are copied over */
4299       (*M)->rmap->bs = mat->rmap->bs;
4300       (*M)->cmap->bs = mat->cmap->bs;
4301       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4302       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4303       (*M)->rmap->mapping = mat->rmap->mapping;
4304       (*M)->cmap->mapping = mat->cmap->mapping;
4305     }
4306     (*M)->stencil.dim = mat->stencil.dim;
4307     (*M)->stencil.noc = mat->stencil.noc;
4308     for (i = 0; i <= mat->stencil.dim; i++) {
4309       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4310       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4311     }
4312     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4313   }
4314   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4315 
4316   /* Copy Mat options */
4317   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4318   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4319   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4320   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4321   PetscFunctionReturn(0);
4322 }
4323 
4324 /*@C
4325    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4326 
4327    Not Collective
4328 
4329    Input Parameter:
4330 .  mat - the matrix, must be a factored matrix
4331 
4332    Output Parameter:
4333 .   type - the string name of the package (do not free this string)
4334 
4335    Notes:
4336       In Fortran you pass in a empty string and the package name will be copied into it.
4337     (Make sure the string is long enough)
4338 
4339    Level: intermediate
4340 
4341 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4342 @*/
4343 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) {
4344   PetscErrorCode (*conv)(Mat, MatSolverType *);
4345 
4346   PetscFunctionBegin;
4347   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4348   PetscValidType(mat, 1);
4349   PetscValidPointer(type, 2);
4350   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4351   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4352   if (conv) PetscCall((*conv)(mat, type));
4353   else *type = MATSOLVERPETSC;
4354   PetscFunctionReturn(0);
4355 }
4356 
4357 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4358 struct _MatSolverTypeForSpecifcType {
4359   MatType mtype;
4360   /* no entry for MAT_FACTOR_NONE */
4361   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4362   MatSolverTypeForSpecifcType next;
4363 };
4364 
4365 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4366 struct _MatSolverTypeHolder {
4367   char                       *name;
4368   MatSolverTypeForSpecifcType handlers;
4369   MatSolverTypeHolder         next;
4370 };
4371 
4372 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4373 
4374 /*@C
4375    MatSolverTypeRegister - Registers a MatSolverType that works for a particular matrix type
4376 
4377    Input Parameters:
4378 +    package - name of the package, for example petsc or superlu
4379 .    mtype - the matrix type that works with this package
4380 .    ftype - the type of factorization supported by the package
4381 -    createfactor - routine that will create the factored matrix ready to be used
4382 
4383     Level: intermediate
4384 
4385 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4386 @*/
4387 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) {
4388   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4389   PetscBool                   flg;
4390   MatSolverTypeForSpecifcType inext, iprev = NULL;
4391 
4392   PetscFunctionBegin;
4393   PetscCall(MatInitializePackage());
4394   if (!next) {
4395     PetscCall(PetscNew(&MatSolverTypeHolders));
4396     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4397     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4398     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4399     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4400     PetscFunctionReturn(0);
4401   }
4402   while (next) {
4403     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4404     if (flg) {
4405       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4406       inext = next->handlers;
4407       while (inext) {
4408         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4409         if (flg) {
4410           inext->createfactor[(int)ftype - 1] = createfactor;
4411           PetscFunctionReturn(0);
4412         }
4413         iprev = inext;
4414         inext = inext->next;
4415       }
4416       PetscCall(PetscNew(&iprev->next));
4417       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4418       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4419       PetscFunctionReturn(0);
4420     }
4421     prev = next;
4422     next = next->next;
4423   }
4424   PetscCall(PetscNew(&prev->next));
4425   PetscCall(PetscStrallocpy(package, &prev->next->name));
4426   PetscCall(PetscNew(&prev->next->handlers));
4427   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4428   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4429   PetscFunctionReturn(0);
4430 }
4431 
4432 /*@C
4433    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4434 
4435    Input Parameters:
4436 +    type - name of the package, for example petsc or superlu
4437 .    ftype - the type of factorization supported by the type
4438 -    mtype - the matrix type that works with this type
4439 
4440    Output Parameters:
4441 +   foundtype - PETSC_TRUE if the type was registered
4442 .   foundmtype - PETSC_TRUE if the type supports the requested mtype
4443 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4444 
4445     Level: intermediate
4446 
4447 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4448 @*/
4449 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) {
4450   MatSolverTypeHolder         next = MatSolverTypeHolders;
4451   PetscBool                   flg;
4452   MatSolverTypeForSpecifcType inext;
4453 
4454   PetscFunctionBegin;
4455   if (foundtype) *foundtype = PETSC_FALSE;
4456   if (foundmtype) *foundmtype = PETSC_FALSE;
4457   if (createfactor) *createfactor = NULL;
4458 
4459   if (type) {
4460     while (next) {
4461       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4462       if (flg) {
4463         if (foundtype) *foundtype = PETSC_TRUE;
4464         inext = next->handlers;
4465         while (inext) {
4466           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4467           if (flg) {
4468             if (foundmtype) *foundmtype = PETSC_TRUE;
4469             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4470             PetscFunctionReturn(0);
4471           }
4472           inext = inext->next;
4473         }
4474       }
4475       next = next->next;
4476     }
4477   } else {
4478     while (next) {
4479       inext = next->handlers;
4480       while (inext) {
4481         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4482         if (flg && inext->createfactor[(int)ftype - 1]) {
4483           if (foundtype) *foundtype = PETSC_TRUE;
4484           if (foundmtype) *foundmtype = PETSC_TRUE;
4485           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4486           PetscFunctionReturn(0);
4487         }
4488         inext = inext->next;
4489       }
4490       next = next->next;
4491     }
4492     /* try with base classes inext->mtype */
4493     next = MatSolverTypeHolders;
4494     while (next) {
4495       inext = next->handlers;
4496       while (inext) {
4497         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4498         if (flg && inext->createfactor[(int)ftype - 1]) {
4499           if (foundtype) *foundtype = PETSC_TRUE;
4500           if (foundmtype) *foundmtype = PETSC_TRUE;
4501           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4502           PetscFunctionReturn(0);
4503         }
4504         inext = inext->next;
4505       }
4506       next = next->next;
4507     }
4508   }
4509   PetscFunctionReturn(0);
4510 }
4511 
4512 PetscErrorCode MatSolverTypeDestroy(void) {
4513   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4514   MatSolverTypeForSpecifcType inext, iprev;
4515 
4516   PetscFunctionBegin;
4517   while (next) {
4518     PetscCall(PetscFree(next->name));
4519     inext = next->handlers;
4520     while (inext) {
4521       PetscCall(PetscFree(inext->mtype));
4522       iprev = inext;
4523       inext = inext->next;
4524       PetscCall(PetscFree(iprev));
4525     }
4526     prev = next;
4527     next = next->next;
4528     PetscCall(PetscFree(prev));
4529   }
4530   MatSolverTypeHolders = NULL;
4531   PetscFunctionReturn(0);
4532 }
4533 
4534 /*@C
4535    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in MatLUFactorSymbolic(), MatCholeskyFactorSymbolic()
4536 
4537    Logically Collective on Mat
4538 
4539    Input Parameters:
4540 .  mat - the matrix
4541 
4542    Output Parameters:
4543 .  flg - PETSC_TRUE if uses the ordering
4544 
4545    Notes:
4546       Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4547       packages do not, thus we want to skip generating the ordering when it is not needed or used.
4548 
4549    Level: developer
4550 
4551 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4552 @*/
4553 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) {
4554   PetscFunctionBegin;
4555   *flg = mat->canuseordering;
4556   PetscFunctionReturn(0);
4557 }
4558 
4559 /*@C
4560    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4561 
4562    Logically Collective on Mat
4563 
4564    Input Parameters:
4565 .  mat - the matrix
4566 
4567    Output Parameters:
4568 .  otype - the preferred type
4569 
4570    Level: developer
4571 
4572 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4573 @*/
4574 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) {
4575   PetscFunctionBegin;
4576   *otype = mat->preferredordering[ftype];
4577   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4578   PetscFunctionReturn(0);
4579 }
4580 
4581 /*@C
4582    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4583 
4584    Collective on Mat
4585 
4586    Input Parameters:
4587 +  mat - the matrix
4588 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4589 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4590 
4591    Output Parameters:
4592 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4593 
4594    Options Database Key:
4595 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4596                                   One can choose host to save device memory). Currently only supported with SEQAIJCUSPARSE matrices.
4597 
4598    Notes:
4599       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4600      such as pastix, superlu, mumps etc.
4601 
4602       PETSc must have been ./configure to use the external solver, using the option --download-package
4603 
4604       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4605       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4606       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4607 
4608    Developer Notes:
4609       This should actually be called MatCreateFactor() since it creates a new factor object
4610 
4611    Level: intermediate
4612 
4613 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`
4614 @*/
4615 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) {
4616   PetscBool foundtype, foundmtype;
4617   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4618 
4619   PetscFunctionBegin;
4620   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4621   PetscValidType(mat, 1);
4622 
4623   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4624   MatCheckPreallocated(mat, 1);
4625 
4626   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4627   if (!foundtype) {
4628     if (type) {
4629       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],
4630               ((PetscObject)mat)->type_name, type);
4631     } else {
4632       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);
4633     }
4634   }
4635   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4636   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);
4637 
4638   PetscCall((*conv)(mat, ftype, f));
4639   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4640   PetscFunctionReturn(0);
4641 }
4642 
4643 /*@C
4644    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4645 
4646    Not Collective
4647 
4648    Input Parameters:
4649 +  mat - the matrix
4650 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4651 -  ftype - factor type, MAT_FACTOR_LU, MAT_FACTOR_CHOLESKY, MAT_FACTOR_ICC, MAT_FACTOR_ILU,
4652 
4653    Output Parameter:
4654 .    flg - PETSC_TRUE if the factorization is available
4655 
4656    Notes:
4657       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4658      such as pastix, superlu, mumps etc.
4659 
4660       PETSc must have been ./configure to use the external solver, using the option --download-package
4661 
4662    Developer Notes:
4663       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4664 
4665    Level: intermediate
4666 
4667 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`
4668 @*/
4669 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) {
4670   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4671 
4672   PetscFunctionBegin;
4673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4674   PetscValidType(mat, 1);
4675   PetscValidBoolPointer(flg, 4);
4676 
4677   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4678   MatCheckPreallocated(mat, 1);
4679 
4680   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4681   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4682   PetscFunctionReturn(0);
4683 }
4684 
4685 /*@
4686    MatDuplicate - Duplicates a matrix including the non-zero structure.
4687 
4688    Collective on Mat
4689 
4690    Input Parameters:
4691 +  mat - the matrix
4692 -  op - One of MAT_DO_NOT_COPY_VALUES, MAT_COPY_VALUES, or MAT_SHARE_NONZERO_PATTERN.
4693         See the manual page for MatDuplicateOption for an explanation of these options.
4694 
4695    Output Parameter:
4696 .  M - pointer to place new matrix
4697 
4698    Level: intermediate
4699 
4700    Notes:
4701     You cannot change the nonzero pattern for the parent or child matrix if you use MAT_SHARE_NONZERO_PATTERN.
4702     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.
4703     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 is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated. 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.
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: `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    Notes:
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()`,
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()`
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()`
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()`
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 Mat
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 Mat
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 SeqAIJ/MPIAIJ matrices. The sequential algorithm
5166    has a running time of the order of the number of nonzeros; the parallel
5167    test involves parallel copies of the block-offdiagonal parts of the matrix.
5168 
5169    Level: intermediate
5170 
5171 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5172 @*/
5173 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) {
5174   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5175 
5176   PetscFunctionBegin;
5177   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5178   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5179   PetscValidBoolPointer(flg, 4);
5180   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5181   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5182   *flg = PETSC_FALSE;
5183   if (f && g) {
5184     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5185     PetscCall((*f)(A, B, tol, flg));
5186   } else {
5187     MatType mattype;
5188 
5189     PetscCall(MatGetType(f ? B : A, &mattype));
5190     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5191   }
5192   PetscFunctionReturn(0);
5193 }
5194 
5195 /*@
5196    MatHermitianTranspose - Computes an in-place or out-of-place transpose of a matrix in complex conjugate.
5197 
5198    Collective on Mat
5199 
5200    Input Parameters:
5201 +  mat - the matrix to transpose and complex conjugate
5202 -  reuse - either MAT_INITIAL_MATRIX, MAT_REUSE_MATRIX, or MAT_INPLACE_MATRIX
5203 
5204    Output Parameter:
5205 .  B - the Hermitian
5206 
5207    Level: intermediate
5208 
5209 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5210 @*/
5211 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) {
5212   PetscFunctionBegin;
5213   PetscCall(MatTranspose(mat, reuse, B));
5214 #if defined(PETSC_USE_COMPLEX)
5215   PetscCall(MatConjugate(*B));
5216 #endif
5217   PetscFunctionReturn(0);
5218 }
5219 
5220 /*@
5221    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5222 
5223    Collective on Mat
5224 
5225    Input Parameters:
5226 +  A - the matrix to test
5227 -  B - the matrix to test against, this can equal the first parameter
5228 
5229    Output Parameters:
5230 .  flg - the result
5231 
5232    Notes:
5233    Only available for SeqAIJ/MPIAIJ matrices. The sequential algorithm
5234    has a running time of the order of the number of nonzeros; the parallel
5235    test involves parallel copies of the block-offdiagonal parts of the matrix.
5236 
5237    Level: intermediate
5238 
5239 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5240 @*/
5241 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) {
5242   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5243 
5244   PetscFunctionBegin;
5245   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5246   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5247   PetscValidBoolPointer(flg, 4);
5248   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5249   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5250   if (f && g) {
5251     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5252     PetscCall((*f)(A, B, tol, flg));
5253   }
5254   PetscFunctionReturn(0);
5255 }
5256 
5257 /*@
5258    MatPermute - Creates a new matrix with rows and columns permuted from the
5259    original.
5260 
5261    Collective on Mat
5262 
5263    Input Parameters:
5264 +  mat - the matrix to permute
5265 .  row - row permutation, each processor supplies only the permutation for its rows
5266 -  col - column permutation, each processor supplies only the permutation for its columns
5267 
5268    Output Parameters:
5269 .  B - the permuted matrix
5270 
5271    Level: advanced
5272 
5273    Note:
5274    The index sets map from row/col of permuted matrix to row/col of original matrix.
5275    The index sets should be on the same communicator as Mat and have the same local sizes.
5276 
5277    Developer Note:
5278      If you want to implement MatPermute for a matrix type, and your approach doesn't
5279      exploit the fact that row and col are permutations, consider implementing the
5280      more general MatCreateSubMatrix() instead.
5281 
5282 .seealso: `MatGetOrdering()`, `ISAllGather()`
5283 
5284 @*/
5285 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) {
5286   PetscFunctionBegin;
5287   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5288   PetscValidType(mat, 1);
5289   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5290   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5291   PetscValidPointer(B, 4);
5292   PetscCheckSameComm(mat, 1, row, 2);
5293   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5294   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5295   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5296   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5297   MatCheckPreallocated(mat, 1);
5298 
5299   if (mat->ops->permute) {
5300     PetscUseTypeMethod(mat, permute, row, col, B);
5301     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5302   } else {
5303     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5304   }
5305   PetscFunctionReturn(0);
5306 }
5307 
5308 /*@
5309    MatEqual - Compares two matrices.
5310 
5311    Collective on Mat
5312 
5313    Input Parameters:
5314 +  A - the first matrix
5315 -  B - the second matrix
5316 
5317    Output Parameter:
5318 .  flg - PETSC_TRUE if the matrices are equal; PETSC_FALSE otherwise.
5319 
5320    Level: intermediate
5321 
5322 @*/
5323 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) {
5324   PetscFunctionBegin;
5325   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5326   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5327   PetscValidType(A, 1);
5328   PetscValidType(B, 2);
5329   PetscValidBoolPointer(flg, 3);
5330   PetscCheckSameComm(A, 1, B, 2);
5331   MatCheckPreallocated(A, 1);
5332   MatCheckPreallocated(B, 2);
5333   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5334   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5335   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,
5336              B->cmap->N);
5337   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5338     PetscUseTypeMethod(A, equal, B, flg);
5339   } else {
5340     PetscCall(MatMultEqual(A, B, 10, flg));
5341   }
5342   PetscFunctionReturn(0);
5343 }
5344 
5345 /*@
5346    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5347    matrices that are stored as vectors.  Either of the two scaling
5348    matrices can be NULL.
5349 
5350    Collective on Mat
5351 
5352    Input Parameters:
5353 +  mat - the matrix to be scaled
5354 .  l - the left scaling vector (or NULL)
5355 -  r - the right scaling vector (or NULL)
5356 
5357    Notes:
5358    MatDiagonalScale() computes A = LAR, where
5359    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5360    The L scales the rows of the matrix, the R scales the columns of the matrix.
5361 
5362    Level: intermediate
5363 
5364 .seealso: `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5365 @*/
5366 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) {
5367   PetscFunctionBegin;
5368   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5369   PetscValidType(mat, 1);
5370   if (l) {
5371     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5372     PetscCheckSameComm(mat, 1, l, 2);
5373   }
5374   if (r) {
5375     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5376     PetscCheckSameComm(mat, 1, r, 3);
5377   }
5378   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5379   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5380   MatCheckPreallocated(mat, 1);
5381   if (!l && !r) PetscFunctionReturn(0);
5382 
5383   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5384   PetscUseTypeMethod(mat, diagonalscale, l, r);
5385   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5386   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5387   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5388   PetscFunctionReturn(0);
5389 }
5390 
5391 /*@
5392     MatScale - Scales all elements of a matrix by a given number.
5393 
5394     Logically Collective on Mat
5395 
5396     Input Parameters:
5397 +   mat - the matrix to be scaled
5398 -   a  - the scaling value
5399 
5400     Output Parameter:
5401 .   mat - the scaled matrix
5402 
5403     Level: intermediate
5404 
5405 .seealso: `MatDiagonalScale()`
5406 @*/
5407 PetscErrorCode MatScale(Mat mat, PetscScalar a) {
5408   PetscFunctionBegin;
5409   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5410   PetscValidType(mat, 1);
5411   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5412   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5413   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5414   PetscValidLogicalCollectiveScalar(mat, a, 2);
5415   MatCheckPreallocated(mat, 1);
5416 
5417   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5418   if (a != (PetscScalar)1.0) {
5419     PetscUseTypeMethod(mat, scale, a);
5420     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5421   }
5422   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5423   PetscFunctionReturn(0);
5424 }
5425 
5426 /*@
5427    MatNorm - Calculates various norms of a matrix.
5428 
5429    Collective on Mat
5430 
5431    Input Parameters:
5432 +  mat - the matrix
5433 -  type - the type of norm, NORM_1, NORM_FROBENIUS, NORM_INFINITY
5434 
5435    Output Parameter:
5436 .  nrm - the resulting norm
5437 
5438    Level: intermediate
5439 
5440 @*/
5441 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) {
5442   PetscFunctionBegin;
5443   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5444   PetscValidType(mat, 1);
5445   PetscValidRealPointer(nrm, 3);
5446 
5447   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5448   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5449   MatCheckPreallocated(mat, 1);
5450 
5451   PetscUseTypeMethod(mat, norm, type, nrm);
5452   PetscFunctionReturn(0);
5453 }
5454 
5455 /*
5456      This variable is used to prevent counting of MatAssemblyBegin() that
5457    are called from within a MatAssemblyEnd().
5458 */
5459 static PetscInt MatAssemblyEnd_InUse = 0;
5460 /*@
5461    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5462    be called after completing all calls to MatSetValues().
5463 
5464    Collective on Mat
5465 
5466    Input Parameters:
5467 +  mat - the matrix
5468 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5469 
5470    Notes:
5471    MatSetValues() generally caches the values.  The matrix is ready to
5472    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5473    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5474    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5475    using the matrix.
5476 
5477    ALL processes that share a matrix MUST call MatAssemblyBegin() and MatAssemblyEnd() the SAME NUMBER of times, and each time with the
5478    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
5479    a global collective operation requring all processes that share the matrix.
5480 
5481    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5482    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5483    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5484 
5485    Level: beginner
5486 
5487 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5488 @*/
5489 PetscErrorCode  MatAssemblyBegin(Mat mat, MatAssemblyType type) {
5490    PetscFunctionBegin;
5491    PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5492    PetscValidType(mat, 1);
5493    MatCheckPreallocated(mat, 1);
5494    PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5495    if (mat->assembled) {
5496      mat->was_assembled = PETSC_TRUE;
5497      mat->assembled     = PETSC_FALSE;
5498   }
5499 
5500    if (!MatAssemblyEnd_InUse) {
5501      PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5502      PetscTryTypeMethod(mat, assemblybegin, type);
5503      PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5504   } else PetscTryTypeMethod(mat, assemblybegin, type);
5505    PetscFunctionReturn(0);
5506 }
5507 
5508 /*@
5509    MatAssembled - Indicates if a matrix has been assembled and is ready for
5510      use; for example, in matrix-vector product.
5511 
5512    Not Collective
5513 
5514    Input Parameter:
5515 .  mat - the matrix
5516 
5517    Output Parameter:
5518 .  assembled - PETSC_TRUE or PETSC_FALSE
5519 
5520    Level: advanced
5521 
5522 .seealso: `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5523 @*/
5524 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) {
5525   PetscFunctionBegin;
5526   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5527   PetscValidBoolPointer(assembled, 2);
5528   *assembled = mat->assembled;
5529   PetscFunctionReturn(0);
5530 }
5531 
5532 /*@
5533    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5534    be called after MatAssemblyBegin().
5535 
5536    Collective on Mat
5537 
5538    Input Parameters:
5539 +  mat - the matrix
5540 -  type - type of assembly, either MAT_FLUSH_ASSEMBLY or MAT_FINAL_ASSEMBLY
5541 
5542    Options Database Keys:
5543 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of MatEndAssembly()
5544 .  -mat_view ::ascii_info_detail - Prints more detailed info
5545 .  -mat_view - Prints matrix in ASCII format
5546 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5547 .  -mat_view draw - PetscDraws nonzero structure of matrix, using MatView() and PetscDrawOpenX().
5548 .  -display <name> - Sets display name (default is host)
5549 .  -draw_pause <sec> - Sets number of seconds to pause after display
5550 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab)
5551 .  -viewer_socket_machine <machine> - Machine to use for socket
5552 .  -viewer_socket_port <port> - Port number to use for socket
5553 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5554 
5555    Notes:
5556    MatSetValues() generally caches the values.  The matrix is ready to
5557    use only after MatAssemblyBegin() and MatAssemblyEnd() have been called.
5558    Use MAT_FLUSH_ASSEMBLY when switching between ADD_VALUES and INSERT_VALUES
5559    in MatSetValues(); use MAT_FINAL_ASSEMBLY for the final assembly before
5560    using the matrix.
5561 
5562    Space for preallocated nonzeros that is not filled by a call to MatSetValues() or a related routine are compressed
5563    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5564    before MAT_FINAL_ASSEMBLY so the space is not compressed out.
5565 
5566    Level: beginner
5567 
5568 .seealso: `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5569 @*/
5570 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) {
5571   static PetscInt inassm = 0;
5572   PetscBool       flg    = PETSC_FALSE;
5573 
5574   PetscFunctionBegin;
5575   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5576   PetscValidType(mat, 1);
5577 
5578   inassm++;
5579   MatAssemblyEnd_InUse++;
5580   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5581     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5582     PetscTryTypeMethod(mat, assemblyend, type);
5583     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5584   } else PetscTryTypeMethod(mat, assemblyend, type);
5585 
5586   /* Flush assembly is not a true assembly */
5587   if (type != MAT_FLUSH_ASSEMBLY) {
5588     if (mat->num_ass) {
5589       if (!mat->symmetry_eternal) {
5590         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5591         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5592       }
5593       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) { mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN; }
5594       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5595     }
5596     mat->num_ass++;
5597     mat->assembled        = PETSC_TRUE;
5598     mat->ass_nonzerostate = mat->nonzerostate;
5599   }
5600 
5601   mat->insertmode = NOT_SET_VALUES;
5602   MatAssemblyEnd_InUse--;
5603   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5604   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5605     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5606 
5607     if (mat->checksymmetryonassembly) {
5608       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5609       if (flg) {
5610         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5611       } else {
5612         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5613       }
5614     }
5615     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5616   }
5617   inassm--;
5618   PetscFunctionReturn(0);
5619 }
5620 
5621 /*@
5622    MatSetOption - Sets a parameter option for a matrix. Some options
5623    may be specific to certain storage formats.  Some options
5624    determine how values will be inserted (or added). Sorted,
5625    row-oriented input will generally assemble the fastest. The default
5626    is row-oriented.
5627 
5628    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5629 
5630    Input Parameters:
5631 +  mat - the matrix
5632 .  option - the option, one of those listed below (and possibly others),
5633 -  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5634 
5635   Options Describing Matrix Structure:
5636 +    MAT_SPD - symmetric positive definite
5637 .    MAT_SYMMETRIC - symmetric in terms of both structure and value
5638 .    MAT_HERMITIAN - transpose is the complex conjugation
5639 .    MAT_STRUCTURALLY_SYMMETRIC - symmetric nonzero structure
5640 .    MAT_SYMMETRY_ETERNAL - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5641 .    MAT_STRUCTURAL_SYMMETRY_ETERNAL - indicates the structural symmetry or its absence will persist through any changes to the matrix
5642 -    MAT_SPD_ETERNAL - indicates the value of MAT_SPD (true or false) will persist through any changes to the matrix
5643 
5644    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5645    do not need to be computed (usually at a high cost)
5646 
5647    Options For Use with MatSetValues():
5648    Insert a logically dense subblock, which can be
5649 .    MAT_ROW_ORIENTED - row-oriented (default)
5650 
5651    Note these options reflect the data you pass in with MatSetValues(); it has
5652    nothing to do with how the data is stored internally in the matrix
5653    data structure.
5654 
5655    When (re)assembling a matrix, we can restrict the input for
5656    efficiency/debugging purposes.  These options include
5657 +    MAT_NEW_NONZERO_LOCATIONS - additional insertions will be allowed if they generate a new nonzero (slow)
5658 .    MAT_FORCE_DIAGONAL_ENTRIES - forces diagonal entries to be allocated
5659 .    MAT_IGNORE_OFF_PROC_ENTRIES - drops off-processor entries
5660 .    MAT_NEW_NONZERO_LOCATION_ERR - generates an error for new matrix entry
5661 .    MAT_USE_HASH_TABLE - uses a hash table to speed up matrix assembly
5662 .    MAT_NO_OFF_PROC_ENTRIES - you know each process will only set values for its own rows, will generate an error if
5663         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5664         performance for very large process counts.
5665 -    MAT_SUBSET_OFF_PROC_ENTRIES - you know that the first assembly after setting this flag will set a superset
5666         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5667         functions, instead sending only neighbor messages.
5668 
5669    Notes:
5670    Except for MAT_UNUSED_NONZERO_LOCATION_ERR and  MAT_ROW_ORIENTED all processes that share the matrix must pass the same value in flg!
5671 
5672    Some options are relevant only for particular matrix types and
5673    are thus ignored by others.  Other options are not supported by
5674    certain matrix types and will generate an error message if set.
5675 
5676    If using a Fortran 77 module to compute a matrix, one may need to
5677    use the column-oriented option (or convert to the row-oriented
5678    format).
5679 
5680    MAT_NEW_NONZERO_LOCATIONS set to PETSC_FALSE indicates that any add or insertion
5681    that would generate a new entry in the nonzero structure is instead
5682    ignored.  Thus, if memory has not alredy been allocated for this particular
5683    data, then the insertion is ignored. For dense matrices, in which
5684    the entire array is allocated, no entries are ever ignored.
5685    Set after the first MatAssemblyEnd(). If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5686 
5687    MAT_NEW_NONZERO_LOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5688    that would generate a new entry in the nonzero structure instead produces
5689    an error. (Currently supported for AIJ and BAIJ formats only.) If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5690 
5691    MAT_NEW_NONZERO_ALLOCATION_ERR set to PETSC_TRUE indicates that any add or insertion
5692    that would generate a new entry that has not been preallocated will
5693    instead produce an error. (Currently supported for AIJ and BAIJ formats
5694    only.) This is a useful flag when debugging matrix memory preallocation.
5695    If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5696 
5697    MAT_IGNORE_OFF_PROC_ENTRIES set to PETSC_TRUE indicates entries destined for
5698    other processors should be dropped, rather than stashed.
5699    This is useful if you know that the "owning" processor is also
5700    always generating the correct matrix entries, so that PETSc need
5701    not transfer duplicate entries generated on another processor.
5702 
5703    MAT_USE_HASH_TABLE indicates that a hash table be used to improve the
5704    searches during matrix assembly. When this flag is set, the hash table
5705    is created during the first Matrix Assembly. This hash table is
5706    used the next time through, during MatSetVaules()/MatSetVaulesBlocked()
5707    to improve the searching of indices. MAT_NEW_NONZERO_LOCATIONS flag
5708    should be used with MAT_USE_HASH_TABLE flag. This option is currently
5709    supported by MATMPIBAIJ format only.
5710 
5711    MAT_KEEP_NONZERO_PATTERN indicates when MatZeroRows() is called the zeroed entries
5712    are kept in the nonzero structure
5713 
5714    MAT_IGNORE_ZERO_ENTRIES - for AIJ/IS matrices this will stop zero values from creating
5715    a zero location in the matrix
5716 
5717    MAT_USE_INODES - indicates using inode version of the code - works with AIJ matrix types
5718 
5719    MAT_NO_OFF_PROC_ZERO_ROWS - you know each process will only zero its own rows. This avoids all reductions in the
5720         zero row routines and thus improves performance for very large process counts.
5721 
5722    MAT_IGNORE_LOWER_TRIANGULAR - For SBAIJ matrices will ignore any insertions you make in the lower triangular
5723         part of the matrix (since they should match the upper triangular part).
5724 
5725    MAT_SORTED_FULL - each process provides exactly its local rows; all column indices for a given row are passed in a
5726                      single call to MatSetValues(), preallocation is perfect, row oriented, INSERT_VALUES is used. Common
5727                      with finite difference schemes with non-periodic boundary conditions.
5728 
5729    Developer Note:
5730    MAT_SYMMETRY_ETERNAL, MAT_STRUCTURAL_SYMMETRY_ETERNAL, and MAT_SPD_ETERNAL are used by MatAssemblyEnd() and in other
5731    places where otherwise the value of MAT_SYMMETRIC, MAT_STRUCTURAL_SYMMETRIC or MAT_SPD would need to be changed back
5732    to PETSC_BOOL3_UNKNOWN because the matrix values had changed so the code cannot be certain that the related property had
5733    not changed.
5734 
5735    Level: intermediate
5736 
5737 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5738 
5739 @*/
5740 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) {
5741   PetscFunctionBegin;
5742   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5743   if (op > 0) {
5744     PetscValidLogicalCollectiveEnum(mat, op, 2);
5745     PetscValidLogicalCollectiveBool(mat, flg, 3);
5746   }
5747 
5748   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);
5749 
5750   switch (op) {
5751   case MAT_FORCE_DIAGONAL_ENTRIES: mat->force_diagonals = flg; PetscFunctionReturn(0);
5752   case MAT_NO_OFF_PROC_ENTRIES: mat->nooffprocentries = flg; PetscFunctionReturn(0);
5753   case MAT_SUBSET_OFF_PROC_ENTRIES:
5754     mat->assembly_subset = flg;
5755     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5756 #if !defined(PETSC_HAVE_MPIUNI)
5757       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5758 #endif
5759       mat->stash.first_assembly_done = PETSC_FALSE;
5760     }
5761     PetscFunctionReturn(0);
5762   case MAT_NO_OFF_PROC_ZERO_ROWS: mat->nooffproczerorows = flg; PetscFunctionReturn(0);
5763   case MAT_SPD:
5764     if (flg) {
5765       mat->spd                    = PETSC_BOOL3_TRUE;
5766       mat->symmetric              = PETSC_BOOL3_TRUE;
5767       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5768     } else {
5769       mat->spd = PETSC_BOOL3_FALSE;
5770     }
5771     break;
5772   case MAT_SYMMETRIC:
5773     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5774     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5775 #if !defined(PETSC_USE_COMPLEX)
5776     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5777 #endif
5778     break;
5779   case MAT_HERMITIAN:
5780     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5781     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5782 #if !defined(PETSC_USE_COMPLEX)
5783     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5784 #endif
5785     break;
5786   case MAT_STRUCTURALLY_SYMMETRIC: mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; break;
5787   case MAT_SYMMETRY_ETERNAL:
5788     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");
5789     mat->symmetry_eternal = flg;
5790     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5791     break;
5792   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5793     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");
5794     mat->structural_symmetry_eternal = flg;
5795     break;
5796   case MAT_SPD_ETERNAL:
5797     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");
5798     mat->spd_eternal = flg;
5799     if (flg) {
5800       mat->structural_symmetry_eternal = PETSC_TRUE;
5801       mat->symmetry_eternal            = PETSC_TRUE;
5802     }
5803     break;
5804   case MAT_STRUCTURE_ONLY: mat->structure_only = flg; break;
5805   case MAT_SORTED_FULL: mat->sortedfull = flg; break;
5806   default: break;
5807   }
5808   PetscTryTypeMethod(mat, setoption, op, flg);
5809   PetscFunctionReturn(0);
5810 }
5811 
5812 /*@
5813    MatGetOption - Gets a parameter option that has been set for a matrix.
5814 
5815    Logically Collective on Mat for certain operations, such as MAT_SPD, not collective for MAT_ROW_ORIENTED, see MatOption
5816 
5817    Input Parameters:
5818 +  mat - the matrix
5819 -  option - the option, this only responds to certain options, check the code for which ones
5820 
5821    Output Parameter:
5822 .  flg - turn the option on (PETSC_TRUE) or off (PETSC_FALSE)
5823 
5824     Notes:
5825     Can only be called after MatSetSizes() and MatSetType() have been set.
5826 
5827     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`, or
5828     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5829 
5830    Level: intermediate
5831 
5832 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`,
5833     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5834 
5835 @*/
5836 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) {
5837   PetscFunctionBegin;
5838   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5839   PetscValidType(mat, 1);
5840 
5841   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);
5842   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()");
5843 
5844   switch (op) {
5845   case MAT_NO_OFF_PROC_ENTRIES: *flg = mat->nooffprocentries; break;
5846   case MAT_NO_OFF_PROC_ZERO_ROWS: *flg = mat->nooffproczerorows; break;
5847   case MAT_SYMMETRIC: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); break;
5848   case MAT_HERMITIAN: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); break;
5849   case MAT_STRUCTURALLY_SYMMETRIC: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); break;
5850   case MAT_SPD: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); break;
5851   case MAT_SYMMETRY_ETERNAL: *flg = mat->symmetry_eternal; break;
5852   case MAT_STRUCTURAL_SYMMETRY_ETERNAL: *flg = mat->symmetry_eternal; break;
5853   default: break;
5854   }
5855   PetscFunctionReturn(0);
5856 }
5857 
5858 /*@
5859    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5860    this routine retains the old nonzero structure.
5861 
5862    Logically Collective on Mat
5863 
5864    Input Parameters:
5865 .  mat - the matrix
5866 
5867    Level: intermediate
5868 
5869    Notes:
5870     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.
5871    See the Performance chapter of the users manual for information on preallocating matrices.
5872 
5873 .seealso: `MatZeroRows()`
5874 @*/
5875 PetscErrorCode MatZeroEntries(Mat mat) {
5876   PetscFunctionBegin;
5877   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5878   PetscValidType(mat, 1);
5879   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5880   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");
5881   MatCheckPreallocated(mat, 1);
5882 
5883   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
5884   PetscUseTypeMethod(mat, zeroentries);
5885   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
5886   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5887   PetscFunctionReturn(0);
5888 }
5889 
5890 /*@
5891    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5892    of a set of rows and columns of a matrix.
5893 
5894    Collective on Mat
5895 
5896    Input Parameters:
5897 +  mat - the matrix
5898 .  numRows - the number of rows to remove
5899 .  rows - the global row indices
5900 .  diag - value put in the diagonal of the eliminated rows
5901 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5902 -  b - optional vector of right hand side, that will be adjusted by provided solution
5903 
5904    Notes:
5905    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5906 
5907    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5908    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
5909 
5910    If the resulting linear system is to be solved with KSP then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5911    Krylov method to take advantage of the known solution on the zeroed rows.
5912 
5913    For the parallel case, all processes that share the matrix (i.e.,
5914    those in the communicator used for matrix creation) MUST call this
5915    routine, regardless of whether any rows being zeroed are owned by
5916    them.
5917 
5918    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5919 
5920    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5921    list only rows local to itself).
5922 
5923    The option MAT_NO_OFF_PROC_ZERO_ROWS does not apply to this routine.
5924 
5925    Level: intermediate
5926 
5927 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5928           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5929 @*/
5930 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
5931   PetscFunctionBegin;
5932   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5933   PetscValidType(mat, 1);
5934   if (numRows) PetscValidIntPointer(rows, 3);
5935   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5936   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5937   MatCheckPreallocated(mat, 1);
5938 
5939   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5940   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5941   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5942   PetscFunctionReturn(0);
5943 }
5944 
5945 /*@
5946    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5947    of a set of rows and columns of a matrix.
5948 
5949    Collective on Mat
5950 
5951    Input Parameters:
5952 +  mat - the matrix
5953 .  is - the rows to zero
5954 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5955 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5956 -  b - optional vector of right hand side, that will be adjusted by provided solution
5957 
5958    Note:
5959    See `MatZeroRowsColumns()` for details on how this routine operates.
5960 
5961    Level: intermediate
5962 
5963 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5964           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
5965 @*/
5966 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
5967   PetscInt        numRows;
5968   const PetscInt *rows;
5969 
5970   PetscFunctionBegin;
5971   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5972   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
5973   PetscValidType(mat, 1);
5974   PetscValidType(is, 2);
5975   PetscCall(ISGetLocalSize(is, &numRows));
5976   PetscCall(ISGetIndices(is, &rows));
5977   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
5978   PetscCall(ISRestoreIndices(is, &rows));
5979   PetscFunctionReturn(0);
5980 }
5981 
5982 /*@
5983    MatZeroRows - Zeros all entries (except possibly the main diagonal)
5984    of a set of rows of a matrix.
5985 
5986    Collective on Mat
5987 
5988    Input Parameters:
5989 +  mat - the matrix
5990 .  numRows - the number of rows to remove
5991 .  rows - the global row indices
5992 .  diag - value put in the diagonal of the eliminated rows
5993 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5994 -  b - optional vector of right hand side, that will be adjusted by provided solution
5995 
5996    Notes:
5997    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5998 
5999    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
6000 
6001    If the resulting linear system is to be solved with KSP then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6002    Krylov method to take advantage of the known solution on the zeroed rows.
6003 
6004    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)
6005    from the matrix.
6006 
6007    Unlike `MatZeroRowsColumns()` for the AIJ and BAIJ matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6008    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
6009    formats this does not alter the nonzero structure.
6010 
6011    If the option MatSetOption(mat,MAT_KEEP_NONZERO_PATTERN,PETSC_TRUE) the nonzero structure
6012    of the matrix is not changed (even for AIJ and BAIJ matrices) the values are
6013    merely zeroed.
6014 
6015    The user can set a value in the diagonal entry (or for the AIJ and
6016    row formats can optionally remove the main diagonal entry from the
6017    nonzero structure as well, by passing 0.0 as the final argument).
6018 
6019    For the parallel case, all processes that share the matrix (i.e.,
6020    those in the communicator used for matrix creation) MUST call this
6021    routine, regardless of whether any rows being zeroed are owned by
6022    them.
6023 
6024    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6025    list only rows local to itself).
6026 
6027    You can call MatSetOption(mat,MAT_NO_OFF_PROC_ZERO_ROWS,PETSC_TRUE) if each process indicates only rows it
6028    owns that are to be zeroed. This saves a global synchronization in the implementation.
6029 
6030    Level: intermediate
6031 
6032 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6033           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6034 @*/
6035 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6036   PetscFunctionBegin;
6037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6038   PetscValidType(mat, 1);
6039   if (numRows) PetscValidIntPointer(rows, 3);
6040   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6041   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6042   MatCheckPreallocated(mat, 1);
6043 
6044   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6045   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6046   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6047   PetscFunctionReturn(0);
6048 }
6049 
6050 /*@
6051    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6052    of a set of rows of a matrix.
6053 
6054    Collective on Mat
6055 
6056    Input Parameters:
6057 +  mat - the matrix
6058 .  is - index set of rows to remove (if NULL then no row is removed)
6059 .  diag - value put in all diagonals of eliminated rows
6060 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6061 -  b - optional vector of right hand side, that will be adjusted by provided solution
6062 
6063    Note:
6064    See `MatZeroRows()` for details on how this routine operates.
6065 
6066    Level: intermediate
6067 
6068 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6069           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6070 @*/
6071 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6072   PetscInt        numRows = 0;
6073   const PetscInt *rows    = NULL;
6074 
6075   PetscFunctionBegin;
6076   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6077   PetscValidType(mat, 1);
6078   if (is) {
6079     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6080     PetscCall(ISGetLocalSize(is, &numRows));
6081     PetscCall(ISGetIndices(is, &rows));
6082   }
6083   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6084   if (is) PetscCall(ISRestoreIndices(is, &rows));
6085   PetscFunctionReturn(0);
6086 }
6087 
6088 /*@
6089    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6090    of a set of rows of a matrix. These rows must be local to the process.
6091 
6092    Collective on Mat
6093 
6094    Input Parameters:
6095 +  mat - the matrix
6096 .  numRows - the number of rows to remove
6097 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6098 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6099 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6100 -  b - optional vector of right hand side, that will be adjusted by provided solution
6101 
6102    Notes:
6103    See `MatZeroRows()` for details on how this routine operates.
6104 
6105    The grid coordinates are across the entire grid, not just the local portion
6106 
6107    In Fortran idxm and idxn should be declared as
6108 $     MatStencil idxm(4,m)
6109    and the values inserted using
6110 $    idxm(MatStencil_i,1) = i
6111 $    idxm(MatStencil_j,1) = j
6112 $    idxm(MatStencil_k,1) = k
6113 $    idxm(MatStencil_c,1) = c
6114    etc
6115 
6116    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6117    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6118    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6119    DM_BOUNDARY_PERIODIC boundary type.
6120 
6121    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
6122    a single value per point) you can skip filling those indices.
6123 
6124    Level: intermediate
6125 
6126 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6127           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6128 @*/
6129 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) {
6130   PetscInt  dim    = mat->stencil.dim;
6131   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6132   PetscInt *dims   = mat->stencil.dims + 1;
6133   PetscInt *starts = mat->stencil.starts;
6134   PetscInt *dxm    = (PetscInt *)rows;
6135   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6136 
6137   PetscFunctionBegin;
6138   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6139   PetscValidType(mat, 1);
6140   if (numRows) PetscValidPointer(rows, 3);
6141 
6142   PetscCall(PetscMalloc1(numRows, &jdxm));
6143   for (i = 0; i < numRows; ++i) {
6144     /* Skip unused dimensions (they are ordered k, j, i, c) */
6145     for (j = 0; j < 3 - sdim; ++j) dxm++;
6146     /* Local index in X dir */
6147     tmp = *dxm++ - starts[0];
6148     /* Loop over remaining dimensions */
6149     for (j = 0; j < dim - 1; ++j) {
6150       /* If nonlocal, set index to be negative */
6151       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6152       /* Update local index */
6153       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6154     }
6155     /* Skip component slot if necessary */
6156     if (mat->stencil.noc) dxm++;
6157     /* Local row number */
6158     if (tmp >= 0) { jdxm[numNewRows++] = tmp; }
6159   }
6160   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6161   PetscCall(PetscFree(jdxm));
6162   PetscFunctionReturn(0);
6163 }
6164 
6165 /*@
6166    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6167    of a set of rows and columns of a matrix.
6168 
6169    Collective on Mat
6170 
6171    Input Parameters:
6172 +  mat - the matrix
6173 .  numRows - the number of rows/columns to remove
6174 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6175 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6176 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6177 -  b - optional vector of right hand side, that will be adjusted by provided solution
6178 
6179    Notes:
6180    See `MatZeroRowsColumns()` for details on how this routine operates.
6181 
6182    The grid coordinates are across the entire grid, not just the local portion
6183 
6184    In Fortran idxm and idxn should be declared as
6185 $     MatStencil idxm(4,m)
6186    and the values inserted using
6187 $    idxm(MatStencil_i,1) = i
6188 $    idxm(MatStencil_j,1) = j
6189 $    idxm(MatStencil_k,1) = k
6190 $    idxm(MatStencil_c,1) = c
6191    etc
6192 
6193    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6194    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6195    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6196    DM_BOUNDARY_PERIODIC boundary type.
6197 
6198    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
6199    a single value per point) you can skip filling those indices.
6200 
6201    Level: intermediate
6202 
6203 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6204           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6205 @*/
6206 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) {
6207   PetscInt  dim    = mat->stencil.dim;
6208   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6209   PetscInt *dims   = mat->stencil.dims + 1;
6210   PetscInt *starts = mat->stencil.starts;
6211   PetscInt *dxm    = (PetscInt *)rows;
6212   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6213 
6214   PetscFunctionBegin;
6215   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6216   PetscValidType(mat, 1);
6217   if (numRows) PetscValidPointer(rows, 3);
6218 
6219   PetscCall(PetscMalloc1(numRows, &jdxm));
6220   for (i = 0; i < numRows; ++i) {
6221     /* Skip unused dimensions (they are ordered k, j, i, c) */
6222     for (j = 0; j < 3 - sdim; ++j) dxm++;
6223     /* Local index in X dir */
6224     tmp = *dxm++ - starts[0];
6225     /* Loop over remaining dimensions */
6226     for (j = 0; j < dim - 1; ++j) {
6227       /* If nonlocal, set index to be negative */
6228       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6229       /* Update local index */
6230       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6231     }
6232     /* Skip component slot if necessary */
6233     if (mat->stencil.noc) dxm++;
6234     /* Local row number */
6235     if (tmp >= 0) { jdxm[numNewRows++] = tmp; }
6236   }
6237   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6238   PetscCall(PetscFree(jdxm));
6239   PetscFunctionReturn(0);
6240 }
6241 
6242 /*@C
6243    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6244    of a set of rows of a matrix; using local numbering of rows.
6245 
6246    Collective on Mat
6247 
6248    Input Parameters:
6249 +  mat - the matrix
6250 .  numRows - the number of rows to remove
6251 .  rows - the local row indices
6252 .  diag - value put in all diagonals of eliminated rows
6253 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6254 -  b - optional vector of right hand side, that will be adjusted by provided solution
6255 
6256    Notes:
6257    Before calling `MatZeroRowsLocal()`, the user must first set the
6258    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6259 
6260    See `MatZeroRows()` for details on how this routine operates.
6261 
6262    Level: intermediate
6263 
6264 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6265           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6266 @*/
6267 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6268   PetscFunctionBegin;
6269   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6270   PetscValidType(mat, 1);
6271   if (numRows) PetscValidIntPointer(rows, 3);
6272   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6273   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6274   MatCheckPreallocated(mat, 1);
6275 
6276   if (mat->ops->zerorowslocal) {
6277     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6278   } else {
6279     IS              is, newis;
6280     const PetscInt *newRows;
6281 
6282     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6283     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6284     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6285     PetscCall(ISGetIndices(newis, &newRows));
6286     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6287     PetscCall(ISRestoreIndices(newis, &newRows));
6288     PetscCall(ISDestroy(&newis));
6289     PetscCall(ISDestroy(&is));
6290   }
6291   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6292   PetscFunctionReturn(0);
6293 }
6294 
6295 /*@
6296    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6297    of a set of rows of a matrix; using local numbering of rows.
6298 
6299    Collective on Mat
6300 
6301    Input Parameters:
6302 +  mat - the matrix
6303 .  is - index set of rows to remove
6304 .  diag - value put in all diagonals of eliminated rows
6305 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6306 -  b - optional vector of right hand side, that will be adjusted by provided solution
6307 
6308    Notes:
6309    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6310    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`.
6311 
6312    See `MatZeroRows()` for details on how this routine operates.
6313 
6314    Level: intermediate
6315 
6316 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6317           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6318 @*/
6319 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6320   PetscInt        numRows;
6321   const PetscInt *rows;
6322 
6323   PetscFunctionBegin;
6324   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6325   PetscValidType(mat, 1);
6326   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6327   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6328   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6329   MatCheckPreallocated(mat, 1);
6330 
6331   PetscCall(ISGetLocalSize(is, &numRows));
6332   PetscCall(ISGetIndices(is, &rows));
6333   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6334   PetscCall(ISRestoreIndices(is, &rows));
6335   PetscFunctionReturn(0);
6336 }
6337 
6338 /*@
6339    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6340    of a set of rows and columns of a matrix; using local numbering of rows.
6341 
6342    Collective on Mat
6343 
6344    Input Parameters:
6345 +  mat - the matrix
6346 .  numRows - the number of rows to remove
6347 .  rows - the global row indices
6348 .  diag - value put in all diagonals of eliminated rows
6349 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6350 -  b - optional vector of right hand side, that will be adjusted by provided solution
6351 
6352    Notes:
6353    Before calling MatZeroRowsColumnsLocal(), the user must first set the
6354    local-to-global mapping by calling MatSetLocalToGlobalMapping().
6355 
6356    See `MatZeroRowsColumns()` for details on how this routine operates.
6357 
6358    Level: intermediate
6359 
6360 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6361           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6362 @*/
6363 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6364   IS              is, newis;
6365   const PetscInt *newRows;
6366 
6367   PetscFunctionBegin;
6368   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6369   PetscValidType(mat, 1);
6370   if (numRows) PetscValidIntPointer(rows, 3);
6371   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6372   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6373   MatCheckPreallocated(mat, 1);
6374 
6375   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6376   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6377   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6378   PetscCall(ISGetIndices(newis, &newRows));
6379   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6380   PetscCall(ISRestoreIndices(newis, &newRows));
6381   PetscCall(ISDestroy(&newis));
6382   PetscCall(ISDestroy(&is));
6383   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6384   PetscFunctionReturn(0);
6385 }
6386 
6387 /*@
6388    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6389    of a set of rows and columns of a matrix; using local numbering of rows.
6390 
6391    Collective on Mat
6392 
6393    Input Parameters:
6394 +  mat - the matrix
6395 .  is - index set of rows to remove
6396 .  diag - value put in all diagonals of eliminated rows
6397 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6398 -  b - optional vector of right hand side, that will be adjusted by provided solution
6399 
6400    Notes:
6401    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6402    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`.
6403 
6404    See `MatZeroRowsColumns()` for details on how this routine operates.
6405 
6406    Level: intermediate
6407 
6408 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6409           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6410 @*/
6411 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6412   PetscInt        numRows;
6413   const PetscInt *rows;
6414 
6415   PetscFunctionBegin;
6416   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6417   PetscValidType(mat, 1);
6418   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6419   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6420   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6421   MatCheckPreallocated(mat, 1);
6422 
6423   PetscCall(ISGetLocalSize(is, &numRows));
6424   PetscCall(ISGetIndices(is, &rows));
6425   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6426   PetscCall(ISRestoreIndices(is, &rows));
6427   PetscFunctionReturn(0);
6428 }
6429 
6430 /*@C
6431    MatGetSize - Returns the numbers of rows and columns in a matrix.
6432 
6433    Not Collective
6434 
6435    Input Parameter:
6436 .  mat - the matrix
6437 
6438    Output Parameters:
6439 +  m - the number of global rows
6440 -  n - the number of global columns
6441 
6442    Note: both output parameters can be NULL on input.
6443 
6444    Level: beginner
6445 
6446 .seealso: `MatGetLocalSize()`
6447 @*/
6448 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) {
6449   PetscFunctionBegin;
6450   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6451   if (m) *m = mat->rmap->N;
6452   if (n) *n = mat->cmap->N;
6453   PetscFunctionReturn(0);
6454 }
6455 
6456 /*@C
6457    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6458    of a matrix. For all matrices this is the local size of the left and right vectors as returned by MatCreateVecs().
6459 
6460    Not Collective
6461 
6462    Input Parameter:
6463 .  mat - the matrix
6464 
6465    Output Parameters:
6466 +  m - the number of local rows, use `NULL` to not obtain this value
6467 -  n - the number of local columns, use `NULL` to not obtain this value
6468 
6469    Level: beginner
6470 
6471 .seealso: `MatGetSize()`
6472 @*/
6473 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) {
6474   PetscFunctionBegin;
6475   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6476   if (m) PetscValidIntPointer(m, 2);
6477   if (n) PetscValidIntPointer(n, 3);
6478   if (m) *m = mat->rmap->n;
6479   if (n) *n = mat->cmap->n;
6480   PetscFunctionReturn(0);
6481 }
6482 
6483 /*@C
6484    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6485    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6486 
6487    Not Collective, unless matrix has not been allocated, then collective on Mat
6488 
6489    Input Parameter:
6490 .  mat - the matrix
6491 
6492    Output Parameters:
6493 +  m - the global index of the first local column, use `NULL` to not obtain this value
6494 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6495 
6496    Level: developer
6497 
6498 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6499 
6500 @*/
6501 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) {
6502   PetscFunctionBegin;
6503   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6504   PetscValidType(mat, 1);
6505   if (m) PetscValidIntPointer(m, 2);
6506   if (n) PetscValidIntPointer(n, 3);
6507   MatCheckPreallocated(mat, 1);
6508   if (m) *m = mat->cmap->rstart;
6509   if (n) *n = mat->cmap->rend;
6510   PetscFunctionReturn(0);
6511 }
6512 
6513 /*@C
6514    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6515    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
6516    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6517 
6518    Not Collective
6519 
6520    Input Parameter:
6521 .  mat - the matrix
6522 
6523    Output Parameters:
6524 +  m - the global index of the first local row, use `NULL` to not obtain this value
6525 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6526 
6527    Note:
6528   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6529   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6530   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6531 
6532    Level: beginner
6533 
6534 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6535           `PetscLayout`
6536 
6537 @*/
6538 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) {
6539   PetscFunctionBegin;
6540   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6541   PetscValidType(mat, 1);
6542   if (m) PetscValidIntPointer(m, 2);
6543   if (n) PetscValidIntPointer(n, 3);
6544   MatCheckPreallocated(mat, 1);
6545   if (m) *m = mat->rmap->rstart;
6546   if (n) *n = mat->rmap->rend;
6547   PetscFunctionReturn(0);
6548 }
6549 
6550 /*@C
6551    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6552    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
6553    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6554 
6555    Not Collective, unless matrix has not been allocated, then collective on Mat
6556 
6557    Input Parameters:
6558 .  mat - the matrix
6559 
6560    Output Parameters:
6561 .  ranges - start of each processors portion plus one more than the total length at the end
6562 
6563    Level: beginner
6564 
6565 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6566 
6567 @*/
6568 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) {
6569   PetscFunctionBegin;
6570   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6571   PetscValidType(mat, 1);
6572   MatCheckPreallocated(mat, 1);
6573   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6574   PetscFunctionReturn(0);
6575 }
6576 
6577 /*@C
6578    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6579    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6580 
6581    Not Collective, unless matrix has not been allocated, then collective on Mat
6582 
6583    Input Parameters:
6584 .  mat - the matrix
6585 
6586    Output Parameters:
6587 .  ranges - start of each processors portion plus one more then the total length at the end
6588 
6589    Level: beginner
6590 
6591 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6592 
6593 @*/
6594 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) {
6595   PetscFunctionBegin;
6596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6597   PetscValidType(mat, 1);
6598   MatCheckPreallocated(mat, 1);
6599   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6600   PetscFunctionReturn(0);
6601 }
6602 
6603 /*@C
6604    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6605    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6606    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6607 
6608    Not Collective
6609 
6610    Input Parameter:
6611 .  A - matrix
6612 
6613    Output Parameters:
6614 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6615 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6616 
6617    Level: intermediate
6618 
6619 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6620 @*/
6621 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) {
6622   PetscErrorCode (*f)(Mat, IS *, IS *);
6623 
6624   PetscFunctionBegin;
6625   MatCheckPreallocated(A, 1);
6626   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6627   if (f) {
6628     PetscCall((*f)(A, rows, cols));
6629   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6630     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6631     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6632   }
6633   PetscFunctionReturn(0);
6634 }
6635 
6636 /*@C
6637    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix.
6638    Uses levels of fill only, not drop tolerance. Use MatLUFactorNumeric()
6639    to complete the factorization.
6640 
6641    Collective on Mat
6642 
6643    Input Parameters:
6644 +  mat - the matrix
6645 .  row - row permutation
6646 .  column - column permutation
6647 -  info - structure containing
6648 $      levels - number of levels of fill.
6649 $      expected fill - as ratio of original fill.
6650 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6651                 missing diagonal entries)
6652 
6653    Output Parameters:
6654 .  fact - new matrix that has been symbolically factored
6655 
6656    Notes:
6657     See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
6658 
6659    Most users should employ the simplified KSP interface for linear solvers
6660    instead of working directly with matrix algebra routines such as this.
6661    See, e.g., KSPCreate().
6662 
6663    Level: developer
6664 
6665 .seealso: `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6666           `MatGetOrdering()`, `MatFactorInfo`
6667 
6668     Note: this uses the definition of level of fill as in Y. Saad, 2003
6669 
6670     Developer Note: fortran interface is not autogenerated as the f90
6671     interface definition cannot be generated correctly [due to MatFactorInfo]
6672 
6673    References:
6674 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6675 @*/
6676 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) {
6677   PetscFunctionBegin;
6678   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6679   PetscValidType(mat, 2);
6680   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6681   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6682   PetscValidPointer(info, 5);
6683   PetscValidPointer(fact, 1);
6684   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6685   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6686   if (!fact->ops->ilufactorsymbolic) {
6687     MatSolverType stype;
6688     PetscCall(MatFactorGetSolverType(fact, &stype));
6689     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6690   }
6691   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6692   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6693   MatCheckPreallocated(mat, 2);
6694 
6695   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6696   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6697   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6698   PetscFunctionReturn(0);
6699 }
6700 
6701 /*@C
6702    MatICCFactorSymbolic - Performs symbolic incomplete
6703    Cholesky factorization for a symmetric matrix.  Use
6704    MatCholeskyFactorNumeric() to complete the factorization.
6705 
6706    Collective on Mat
6707 
6708    Input Parameters:
6709 +  mat - the matrix
6710 .  perm - row and column permutation
6711 -  info - structure containing
6712 $      levels - number of levels of fill.
6713 $      expected fill - as ratio of original fill.
6714 
6715    Output Parameter:
6716 .  fact - the factored matrix
6717 
6718    Notes:
6719    Most users should employ the KSP interface for linear solvers
6720    instead of working directly with matrix algebra routines such as this.
6721    See, e.g., KSPCreate().
6722 
6723    Level: developer
6724 
6725 .seealso: `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6726 
6727     Note: this uses the definition of level of fill as in Y. Saad, 2003
6728 
6729     Developer Note: fortran interface is not autogenerated as the f90
6730     interface definition cannot be generated correctly [due to MatFactorInfo]
6731 
6732    References:
6733 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6734 @*/
6735 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) {
6736   PetscFunctionBegin;
6737   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6738   PetscValidType(mat, 2);
6739   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6740   PetscValidPointer(info, 4);
6741   PetscValidPointer(fact, 1);
6742   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6743   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6744   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6745   if (!(fact)->ops->iccfactorsymbolic) {
6746     MatSolverType stype;
6747     PetscCall(MatFactorGetSolverType(fact, &stype));
6748     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6749   }
6750   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6751   MatCheckPreallocated(mat, 2);
6752 
6753   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6754   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6755   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6756   PetscFunctionReturn(0);
6757 }
6758 
6759 /*@C
6760    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6761    points to an array of valid matrices, they may be reused to store the new
6762    submatrices.
6763 
6764    Collective on Mat
6765 
6766    Input Parameters:
6767 +  mat - the matrix
6768 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6769 .  irow, icol - index sets of rows and columns to extract
6770 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6771 
6772    Output Parameter:
6773 .  submat - the array of submatrices
6774 
6775    Notes:
6776    MatCreateSubMatrices() can extract ONLY sequential submatrices
6777    (from both sequential and parallel matrices). Use MatCreateSubMatrix()
6778    to extract a parallel submatrix.
6779 
6780    Some matrix types place restrictions on the row and column
6781    indices, such as that they be sorted or that they be equal to each other.
6782 
6783    The index sets may not have duplicate entries.
6784 
6785    When extracting submatrices from a parallel matrix, each processor can
6786    form a different submatrix by setting the rows and columns of its
6787    individual index sets according to the local submatrix desired.
6788 
6789    When finished using the submatrices, the user should destroy
6790    them with MatDestroySubMatrices().
6791 
6792    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
6793    original matrix has not changed from that last call to MatCreateSubMatrices().
6794 
6795    This routine creates the matrices in submat; you should NOT create them before
6796    calling it. It also allocates the array of matrix pointers submat.
6797 
6798    For BAIJ matrices the index sets must respect the block structure, that is if they
6799    request one row/column in a block, they must request all rows/columns that are in
6800    that block. For example, if the block size is 2 you cannot request just row 0 and
6801    column 0.
6802 
6803    Fortran Note:
6804    The Fortran interface is slightly different from that given below; it
6805    requires one to pass in  as submat a Mat (integer) array of size at least n+1.
6806 
6807    Level: advanced
6808 
6809 .seealso: `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6810 @*/
6811 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) {
6812   PetscInt  i;
6813   PetscBool eq;
6814 
6815   PetscFunctionBegin;
6816   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6817   PetscValidType(mat, 1);
6818   if (n) {
6819     PetscValidPointer(irow, 3);
6820     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
6821     PetscValidPointer(icol, 4);
6822     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
6823   }
6824   PetscValidPointer(submat, 6);
6825   if (n && scall == MAT_REUSE_MATRIX) {
6826     PetscValidPointer(*submat, 6);
6827     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
6828   }
6829   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6830   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6831   MatCheckPreallocated(mat, 1);
6832   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
6833   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6834   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
6835   for (i = 0; i < n; i++) {
6836     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6837     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
6838     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
6839 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6840     if (mat->boundtocpu && mat->bindingpropagates) {
6841       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
6842       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
6843     }
6844 #endif
6845   }
6846   PetscFunctionReturn(0);
6847 }
6848 
6849 /*@C
6850    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of IS that may live on subcomms).
6851 
6852    Collective on Mat
6853 
6854    Input Parameters:
6855 +  mat - the matrix
6856 .  n   - the number of submatrixes to be extracted
6857 .  irow, icol - index sets of rows and columns to extract
6858 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
6859 
6860    Output Parameter:
6861 .  submat - the array of submatrices
6862 
6863    Level: advanced
6864 
6865 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6866 @*/
6867 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) {
6868   PetscInt  i;
6869   PetscBool eq;
6870 
6871   PetscFunctionBegin;
6872   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6873   PetscValidType(mat, 1);
6874   if (n) {
6875     PetscValidPointer(irow, 3);
6876     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
6877     PetscValidPointer(icol, 4);
6878     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
6879   }
6880   PetscValidPointer(submat, 6);
6881   if (n && scall == MAT_REUSE_MATRIX) {
6882     PetscValidPointer(*submat, 6);
6883     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
6884   }
6885   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6886   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6887   MatCheckPreallocated(mat, 1);
6888 
6889   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
6890   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6891   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
6892   for (i = 0; i < n; i++) {
6893     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
6894     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
6895   }
6896   PetscFunctionReturn(0);
6897 }
6898 
6899 /*@C
6900    MatDestroyMatrices - Destroys an array of matrices.
6901 
6902    Collective on Mat
6903 
6904    Input Parameters:
6905 +  n - the number of local matrices
6906 -  mat - the matrices (note that this is a pointer to the array of matrices)
6907 
6908    Level: advanced
6909 
6910     Notes:
6911     Frees not only the matrices, but also the array that contains the matrices
6912            In Fortran will not free the array.
6913 
6914 .seealso: `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6915 @*/
6916 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) {
6917   PetscInt i;
6918 
6919   PetscFunctionBegin;
6920   if (!*mat) PetscFunctionReturn(0);
6921   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
6922   PetscValidPointer(mat, 2);
6923 
6924   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
6925 
6926   /* memory is allocated even if n = 0 */
6927   PetscCall(PetscFree(*mat));
6928   PetscFunctionReturn(0);
6929 }
6930 
6931 /*@C
6932    MatDestroySubMatrices - Destroys a set of matrices obtained with MatCreateSubMatrices().
6933 
6934    Collective on Mat
6935 
6936    Input Parameters:
6937 +  n - the number of local matrices
6938 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6939                        sequence of MatCreateSubMatrices())
6940 
6941    Level: advanced
6942 
6943     Notes:
6944     Frees not only the matrices, but also the array that contains the matrices
6945            In Fortran will not free the array.
6946 
6947 .seealso: `MatCreateSubMatrices()`
6948 @*/
6949 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) {
6950   Mat mat0;
6951 
6952   PetscFunctionBegin;
6953   if (!*mat) PetscFunctionReturn(0);
6954   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
6955   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
6956   PetscValidPointer(mat, 2);
6957 
6958   mat0 = (*mat)[0];
6959   if (mat0 && mat0->ops->destroysubmatrices) {
6960     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
6961   } else {
6962     PetscCall(MatDestroyMatrices(n, mat));
6963   }
6964   PetscFunctionReturn(0);
6965 }
6966 
6967 /*@C
6968    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
6969 
6970    Collective on Mat
6971 
6972    Input Parameters:
6973 .  mat - the matrix
6974 
6975    Output Parameter:
6976 .  matstruct - the sequential matrix with the nonzero structure of mat
6977 
6978   Level: intermediate
6979 
6980 .seealso: `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6981 @*/
6982 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) {
6983   PetscFunctionBegin;
6984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6985   PetscValidPointer(matstruct, 2);
6986 
6987   PetscValidType(mat, 1);
6988   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6989   MatCheckPreallocated(mat, 1);
6990 
6991   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
6992   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
6993   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
6994   PetscFunctionReturn(0);
6995 }
6996 
6997 /*@C
6998    MatDestroySeqNonzeroStructure - Destroys matrix obtained with MatGetSeqNonzeroStructure().
6999 
7000    Collective on Mat
7001 
7002    Input Parameters:
7003 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7004                        sequence of MatGetSequentialNonzeroStructure())
7005 
7006    Level: advanced
7007 
7008     Notes:
7009     Frees not only the matrices, but also the array that contains the matrices
7010 
7011 .seealso: `MatGetSeqNonzeroStructure()`
7012 @*/
7013 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) {
7014   PetscFunctionBegin;
7015   PetscValidPointer(mat, 1);
7016   PetscCall(MatDestroy(mat));
7017   PetscFunctionReturn(0);
7018 }
7019 
7020 /*@
7021    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7022    replaces the index sets by larger ones that represent submatrices with
7023    additional overlap.
7024 
7025    Collective on Mat
7026 
7027    Input Parameters:
7028 +  mat - the matrix
7029 .  n   - the number of index sets
7030 .  is  - the array of index sets (these index sets will changed during the call)
7031 -  ov  - the additional overlap requested
7032 
7033    Options Database:
7034 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7035 
7036    Level: developer
7037 
7038    Developer Note:
7039    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.
7040 
7041 .seealso: `MatCreateSubMatrices()`
7042 @*/
7043 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) {
7044   PetscInt i, bs, cbs;
7045 
7046   PetscFunctionBegin;
7047   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7048   PetscValidType(mat, 1);
7049   PetscValidLogicalCollectiveInt(mat, n, 2);
7050   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7051   if (n) {
7052     PetscValidPointer(is, 3);
7053     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7054   }
7055   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7056   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7057   MatCheckPreallocated(mat, 1);
7058 
7059   if (!ov || !n) PetscFunctionReturn(0);
7060   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7061   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7062   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7063   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7064   if (bs == cbs) {
7065     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7066   }
7067   PetscFunctionReturn(0);
7068 }
7069 
7070 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7071 
7072 /*@
7073    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7074    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7075    additional overlap.
7076 
7077    Collective on Mat
7078 
7079    Input Parameters:
7080 +  mat - the matrix
7081 .  n   - the number of index sets
7082 .  is  - the array of index sets (these index sets will changed during the call)
7083 -  ov  - the additional overlap requested
7084 
7085    Options Database:
7086 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7087 
7088    Level: developer
7089 
7090 .seealso: `MatCreateSubMatrices()`
7091 @*/
7092 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) {
7093   PetscInt i;
7094 
7095   PetscFunctionBegin;
7096   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7097   PetscValidType(mat, 1);
7098   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7099   if (n) {
7100     PetscValidPointer(is, 3);
7101     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7102   }
7103   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7104   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7105   MatCheckPreallocated(mat, 1);
7106   if (!ov) PetscFunctionReturn(0);
7107   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7108   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7109   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7110   PetscFunctionReturn(0);
7111 }
7112 
7113 /*@
7114    MatGetBlockSize - Returns the matrix block size.
7115 
7116    Not Collective
7117 
7118    Input Parameter:
7119 .  mat - the matrix
7120 
7121    Output Parameter:
7122 .  bs - block size
7123 
7124    Notes:
7125     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7126 
7127    If the block size has not been set yet this routine returns 1.
7128 
7129    Level: intermediate
7130 
7131 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7132 @*/
7133 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) {
7134   PetscFunctionBegin;
7135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7136   PetscValidIntPointer(bs, 2);
7137   *bs = PetscAbs(mat->rmap->bs);
7138   PetscFunctionReturn(0);
7139 }
7140 
7141 /*@
7142    MatGetBlockSizes - Returns the matrix block row and column sizes.
7143 
7144    Not Collective
7145 
7146    Input Parameter:
7147 .  mat - the matrix
7148 
7149    Output Parameters:
7150 +  rbs - row block size
7151 -  cbs - column block size
7152 
7153    Notes:
7154     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7155     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7156 
7157    If a block size has not been set yet this routine returns 1.
7158 
7159    Level: intermediate
7160 
7161 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7162 @*/
7163 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) {
7164   PetscFunctionBegin;
7165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7166   if (rbs) PetscValidIntPointer(rbs, 2);
7167   if (cbs) PetscValidIntPointer(cbs, 3);
7168   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7169   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7170   PetscFunctionReturn(0);
7171 }
7172 
7173 /*@
7174    MatSetBlockSize - Sets the matrix block size.
7175 
7176    Logically Collective on Mat
7177 
7178    Input Parameters:
7179 +  mat - the matrix
7180 -  bs - block size
7181 
7182    Notes:
7183     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7184     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7185 
7186     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block size
7187     is compatible with the matrix local sizes.
7188 
7189    Level: intermediate
7190 
7191 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7192 @*/
7193 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) {
7194   PetscFunctionBegin;
7195   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7196   PetscValidLogicalCollectiveInt(mat, bs, 2);
7197   PetscCall(MatSetBlockSizes(mat, bs, bs));
7198   PetscFunctionReturn(0);
7199 }
7200 
7201 typedef struct {
7202   PetscInt         n;
7203   IS              *is;
7204   Mat             *mat;
7205   PetscObjectState nonzerostate;
7206   Mat              C;
7207 } EnvelopeData;
7208 
7209 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) {
7210   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7211   PetscCall(PetscFree(edata->is));
7212   PetscCall(PetscFree(edata));
7213   return 0;
7214 }
7215 
7216 /*
7217    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7218          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7219 
7220    Collective on mat
7221 
7222    Input Parameter:
7223 .  mat - the matrix
7224 
7225    Notes:
7226      There can be zeros within the blocks
7227 
7228      The blocks can overlap between processes, including laying on more than two processes
7229 
7230 */
7231 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) {
7232   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7233   PetscInt          *diag, *odiag, sc;
7234   VecScatter         scatter;
7235   PetscScalar       *seqv;
7236   const PetscScalar *parv;
7237   const PetscInt    *ia, *ja;
7238   PetscBool          set, flag, done;
7239   Mat                AA = mat, A;
7240   MPI_Comm           comm;
7241   PetscMPIInt        rank, size, tag;
7242   MPI_Status         status;
7243   PetscContainer     container;
7244   EnvelopeData      *edata;
7245   Vec                seq, par;
7246   IS                 isglobal;
7247 
7248   PetscFunctionBegin;
7249   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7250   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7251   if (!set || !flag) {
7252     /* TOO: only needs nonzero structure of transpose */
7253     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7254     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7255   }
7256   PetscCall(MatAIJGetLocalMat(AA, &A));
7257   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7258   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7259 
7260   PetscCall(MatGetLocalSize(mat, &n, NULL));
7261   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7262   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7263   PetscCallMPI(MPI_Comm_size(comm, &size));
7264   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7265 
7266   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7267 
7268   if (rank > 0) {
7269     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7270     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7271   }
7272   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7273   for (i = 0; i < n; i++) {
7274     env = PetscMax(env, ja[ia[i + 1] - 1]);
7275     II  = rstart + i;
7276     if (env == II) {
7277       starts[lblocks]  = tbs;
7278       sizes[lblocks++] = 1 + II - tbs;
7279       tbs              = 1 + II;
7280     }
7281   }
7282   if (rank < size - 1) {
7283     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7284     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7285   }
7286 
7287   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7288   if (!set || !flag) PetscCall(MatDestroy(&AA));
7289   PetscCall(MatDestroy(&A));
7290 
7291   PetscCall(PetscNew(&edata));
7292   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7293   edata->n = lblocks;
7294   /* create IS needed for extracting blocks from the original matrix */
7295   PetscCall(PetscMalloc1(lblocks, &edata->is));
7296   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7297 
7298   /* Create the resulting inverse matrix structure with preallocation information */
7299   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7300   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7301   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7302   PetscCall(MatSetType(edata->C, MATAIJ));
7303 
7304   /* Communicate the start and end of each row, from each block to the correct rank */
7305   /* TODO: Use PetscSF instead of VecScatter */
7306   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7307   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7308   PetscCall(VecGetArrayWrite(seq, &seqv));
7309   for (PetscInt i = 0; i < lblocks; i++) {
7310     for (PetscInt j = 0; j < sizes[i]; j++) {
7311       seqv[cnt]     = starts[i];
7312       seqv[cnt + 1] = starts[i] + sizes[i];
7313       cnt += 2;
7314     }
7315   }
7316   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7317   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7318   sc -= cnt;
7319   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7320   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7321   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7322   PetscCall(ISDestroy(&isglobal));
7323   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7324   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7325   PetscCall(VecScatterDestroy(&scatter));
7326   PetscCall(VecDestroy(&seq));
7327   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7328   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7329   PetscCall(VecGetArrayRead(par, &parv));
7330   cnt = 0;
7331   PetscCall(MatGetSize(mat, NULL, &n));
7332   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7333     PetscInt start, end, d = 0, od = 0;
7334 
7335     start = (PetscInt)PetscRealPart(parv[cnt]);
7336     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7337     cnt += 2;
7338 
7339     if (start < cstart) {
7340       od += cstart - start + n - cend;
7341       d += cend - cstart;
7342     } else if (start < cend) {
7343       od += n - cend;
7344       d += cend - start;
7345     } else od += n - start;
7346     if (end <= cstart) {
7347       od -= cstart - end + n - cend;
7348       d -= cend - cstart;
7349     } else if (end < cend) {
7350       od -= n - cend;
7351       d -= cend - end;
7352     } else od -= n - end;
7353 
7354     odiag[i] = od;
7355     diag[i]  = d;
7356   }
7357   PetscCall(VecRestoreArrayRead(par, &parv));
7358   PetscCall(VecDestroy(&par));
7359   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7360   PetscCall(PetscFree2(diag, odiag));
7361   PetscCall(PetscFree2(sizes, starts));
7362 
7363   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7364   PetscCall(PetscContainerSetPointer(container, edata));
7365   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7366   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7367   PetscCall(PetscObjectDereference((PetscObject)container));
7368   PetscFunctionReturn(0);
7369 }
7370 
7371 /*@
7372   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7373 
7374   Collective on Mat
7375 
7376   Input Parameters:
7377 . A - the matrix
7378 
7379   Output Parameters:
7380 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7381 
7382   Notes:
7383      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7384 
7385   Level: advanced
7386 
7387 .seealso: MatInvertBlockDiagonal(), MatComputeBlockDiagonal()
7388 @*/
7389 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) {
7390   PetscContainer   container;
7391   EnvelopeData    *edata;
7392   PetscObjectState nonzerostate;
7393 
7394   PetscFunctionBegin;
7395   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7396   if (!container) {
7397     PetscCall(MatComputeVariableBlockEnvelope(A));
7398     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7399   }
7400   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7401   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7402   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7403   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7404 
7405   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7406   *C = edata->C;
7407 
7408   for (PetscInt i = 0; i < edata->n; i++) {
7409     Mat          D;
7410     PetscScalar *dvalues;
7411 
7412     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7413     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7414     PetscCall(MatSeqDenseInvert(D));
7415     PetscCall(MatDenseGetArray(D, &dvalues));
7416     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7417     PetscCall(MatDestroy(&D));
7418   }
7419   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7420   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7421   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7422   PetscFunctionReturn(0);
7423 }
7424 
7425 /*@
7426    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7427 
7428    Logically Collective on Mat
7429 
7430    Input Parameters:
7431 +  mat - the matrix
7432 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7433 -  bsizes - the block sizes
7434 
7435    Notes:
7436     Currently used by PCVPBJACOBI for AIJ matrices
7437 
7438     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.
7439 
7440    Level: intermediate
7441 
7442 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7443 @*/
7444 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) {
7445   PetscInt i, ncnt = 0, nlocal;
7446 
7447   PetscFunctionBegin;
7448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7449   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7450   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7451   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7452   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);
7453   PetscCall(PetscFree(mat->bsizes));
7454   mat->nblocks = nblocks;
7455   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7456   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7457   PetscFunctionReturn(0);
7458 }
7459 
7460 /*@C
7461    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7462 
7463    Logically Collective on Mat
7464 
7465    Input Parameter:
7466 .  mat - the matrix
7467 
7468    Output Parameters:
7469 +  nblocks - the number of blocks on this process
7470 -  bsizes - the block sizes
7471 
7472    Notes: Currently not supported from Fortran
7473 
7474    Level: intermediate
7475 
7476 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7477 @*/
7478 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) {
7479   PetscFunctionBegin;
7480   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7481   *nblocks = mat->nblocks;
7482   *bsizes  = mat->bsizes;
7483   PetscFunctionReturn(0);
7484 }
7485 
7486 /*@
7487    MatSetBlockSizes - Sets the matrix block row and column sizes.
7488 
7489    Logically Collective on Mat
7490 
7491    Input Parameters:
7492 +  mat - the matrix
7493 .  rbs - row block size
7494 -  cbs - column block size
7495 
7496    Notes:
7497     Block row formats are MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ. These formats ALWAYS have square block storage in the matrix.
7498     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7499     This must be called before MatSetUp() or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7500 
7501     For MATMPIAIJ and MATSEQAIJ matrix formats, this function can be called at a later stage, provided that the specified block sizes
7502     are compatible with the matrix local sizes.
7503 
7504     The row and column block size determine the blocksize of the "row" and "column" vectors returned by MatCreateVecs().
7505 
7506    Level: intermediate
7507 
7508 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7509 @*/
7510 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) {
7511   PetscFunctionBegin;
7512   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7513   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7514   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7515   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7516   if (mat->rmap->refcnt) {
7517     ISLocalToGlobalMapping l2g  = NULL;
7518     PetscLayout            nmap = NULL;
7519 
7520     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7521     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7522     PetscCall(PetscLayoutDestroy(&mat->rmap));
7523     mat->rmap          = nmap;
7524     mat->rmap->mapping = l2g;
7525   }
7526   if (mat->cmap->refcnt) {
7527     ISLocalToGlobalMapping l2g  = NULL;
7528     PetscLayout            nmap = NULL;
7529 
7530     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7531     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7532     PetscCall(PetscLayoutDestroy(&mat->cmap));
7533     mat->cmap          = nmap;
7534     mat->cmap->mapping = l2g;
7535   }
7536   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7537   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7538   PetscFunctionReturn(0);
7539 }
7540 
7541 /*@
7542    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7543 
7544    Logically Collective on Mat
7545 
7546    Input Parameters:
7547 +  mat - the matrix
7548 .  fromRow - matrix from which to copy row block size
7549 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7550 
7551    Level: developer
7552 
7553 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7554 @*/
7555 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) {
7556   PetscFunctionBegin;
7557   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7558   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7559   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7560   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7561   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7562   PetscFunctionReturn(0);
7563 }
7564 
7565 /*@
7566    MatResidual - Default routine to calculate the residual.
7567 
7568    Collective on Mat
7569 
7570    Input Parameters:
7571 +  mat - the matrix
7572 .  b   - the right-hand-side
7573 -  x   - the approximate solution
7574 
7575    Output Parameter:
7576 .  r - location to store the residual
7577 
7578    Level: developer
7579 
7580 .seealso: `PCMGSetResidual()`
7581 @*/
7582 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) {
7583   PetscFunctionBegin;
7584   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7585   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7586   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7587   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7588   PetscValidType(mat, 1);
7589   MatCheckPreallocated(mat, 1);
7590   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7591   if (!mat->ops->residual) {
7592     PetscCall(MatMult(mat, x, r));
7593     PetscCall(VecAYPX(r, -1.0, b));
7594   } else {
7595     PetscUseTypeMethod(mat, residual, b, x, r);
7596   }
7597   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7598   PetscFunctionReturn(0);
7599 }
7600 
7601 /*@C
7602     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7603 
7604    Collective on Mat
7605 
7606     Input Parameters:
7607 +   mat - the matrix
7608 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7609 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be   symmetrized
7610 -   inodecompressed - PETSC_TRUE or PETSC_FALSE  indicating if the nonzero structure of the
7611                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7612                  always used.
7613 
7614     Output Parameters:
7615 +   n - number of local rows in the (possibly compressed) matrix
7616 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7617 .   ja - the column indices
7618 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7619            are responsible for handling the case when done == PETSC_FALSE and ia and ja are not set
7620 
7621     Level: developer
7622 
7623     Notes:
7624     You CANNOT change any of the ia[] or ja[] values.
7625 
7626     Use MatRestoreRowIJ() when you are finished accessing the ia[] and ja[] values.
7627 
7628     Fortran Notes:
7629     In Fortran use
7630 $
7631 $      PetscInt ia(1), ja(1)
7632 $      PetscOffset iia, jja
7633 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7634 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7635 
7636      or
7637 $
7638 $    PetscInt, pointer :: ia(:),ja(:)
7639 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7640 $    ! Access the ith and jth entries via ia(i) and ja(j)
7641 
7642 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7643 @*/
7644 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7645   PetscFunctionBegin;
7646   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7647   PetscValidType(mat, 1);
7648   if (n) PetscValidIntPointer(n, 5);
7649   if (ia) PetscValidPointer(ia, 6);
7650   if (ja) PetscValidPointer(ja, 7);
7651   if (done) PetscValidBoolPointer(done, 8);
7652   MatCheckPreallocated(mat, 1);
7653   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7654   else {
7655     if (done) *done = PETSC_TRUE;
7656     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7657     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7658     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7659   }
7660   PetscFunctionReturn(0);
7661 }
7662 
7663 /*@C
7664     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7665 
7666     Collective on Mat
7667 
7668     Input Parameters:
7669 +   mat - the matrix
7670 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7671 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7672                 symmetrized
7673 .   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7674                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7675                  always used.
7676 .   n - number of columns in the (possibly compressed) matrix
7677 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7678 -   ja - the row indices
7679 
7680     Output Parameters:
7681 .   done - PETSC_TRUE or PETSC_FALSE, indicating whether the values have been returned
7682 
7683     Level: developer
7684 
7685 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7686 @*/
7687 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7688   PetscFunctionBegin;
7689   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7690   PetscValidType(mat, 1);
7691   PetscValidIntPointer(n, 5);
7692   if (ia) PetscValidPointer(ia, 6);
7693   if (ja) PetscValidPointer(ja, 7);
7694   PetscValidBoolPointer(done, 8);
7695   MatCheckPreallocated(mat, 1);
7696   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7697   else {
7698     *done = PETSC_TRUE;
7699     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7700   }
7701   PetscFunctionReturn(0);
7702 }
7703 
7704 /*@C
7705     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with
7706     MatGetRowIJ().
7707 
7708     Collective on Mat
7709 
7710     Input Parameters:
7711 +   mat - the matrix
7712 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7713 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7714                 symmetrized
7715 .   inodecompressed -  PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7716                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7717                  always used.
7718 .   n - size of (possibly compressed) matrix
7719 .   ia - the row pointers
7720 -   ja - the column indices
7721 
7722     Output Parameters:
7723 .   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7724 
7725     Note:
7726     This routine zeros out n, ia, and ja. This is to prevent accidental
7727     us of the array after it has been restored. If you pass NULL, it will
7728     not zero the pointers.  Use of ia or ja after MatRestoreRowIJ() is invalid.
7729 
7730     Level: developer
7731 
7732 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7733 @*/
7734 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7735   PetscFunctionBegin;
7736   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7737   PetscValidType(mat, 1);
7738   if (ia) PetscValidPointer(ia, 6);
7739   if (ja) PetscValidPointer(ja, 7);
7740   if (done) PetscValidBoolPointer(done, 8);
7741   MatCheckPreallocated(mat, 1);
7742 
7743   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7744   else {
7745     if (done) *done = PETSC_TRUE;
7746     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7747     if (n) *n = 0;
7748     if (ia) *ia = NULL;
7749     if (ja) *ja = NULL;
7750   }
7751   PetscFunctionReturn(0);
7752 }
7753 
7754 /*@C
7755     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with
7756     MatGetColumnIJ().
7757 
7758     Collective on Mat
7759 
7760     Input Parameters:
7761 +   mat - the matrix
7762 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7763 .   symmetric - PETSC_TRUE or PETSC_FALSE indicating the matrix data structure should be
7764                 symmetrized
7765 -   inodecompressed - PETSC_TRUE or PETSC_FALSE indicating if the nonzero structure of the
7766                  inodes or the nonzero elements is wanted. For BAIJ matrices the compressed version is
7767                  always used.
7768 
7769     Output Parameters:
7770 +   n - size of (possibly compressed) matrix
7771 .   ia - the column pointers
7772 .   ja - the row indices
7773 -   done - PETSC_TRUE or PETSC_FALSE indicated that the values have been returned
7774 
7775     Level: developer
7776 
7777 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7778 @*/
7779 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7780   PetscFunctionBegin;
7781   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7782   PetscValidType(mat, 1);
7783   if (ia) PetscValidPointer(ia, 6);
7784   if (ja) PetscValidPointer(ja, 7);
7785   PetscValidBoolPointer(done, 8);
7786   MatCheckPreallocated(mat, 1);
7787 
7788   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7789   else {
7790     *done = PETSC_TRUE;
7791     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7792     if (n) *n = 0;
7793     if (ia) *ia = NULL;
7794     if (ja) *ja = NULL;
7795   }
7796   PetscFunctionReturn(0);
7797 }
7798 
7799 /*@C
7800     MatColoringPatch -Used inside matrix coloring routines that
7801     use MatGetRowIJ() and/or MatGetColumnIJ().
7802 
7803     Collective on Mat
7804 
7805     Input Parameters:
7806 +   mat - the matrix
7807 .   ncolors - max color value
7808 .   n   - number of entries in colorarray
7809 -   colorarray - array indicating color for each column
7810 
7811     Output Parameters:
7812 .   iscoloring - coloring generated using colorarray information
7813 
7814     Level: developer
7815 
7816 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7817 
7818 @*/
7819 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) {
7820   PetscFunctionBegin;
7821   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7822   PetscValidType(mat, 1);
7823   PetscValidIntPointer(colorarray, 4);
7824   PetscValidPointer(iscoloring, 5);
7825   MatCheckPreallocated(mat, 1);
7826 
7827   if (!mat->ops->coloringpatch) {
7828     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
7829   } else {
7830     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7831   }
7832   PetscFunctionReturn(0);
7833 }
7834 
7835 /*@
7836    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7837 
7838    Logically Collective on Mat
7839 
7840    Input Parameter:
7841 .  mat - the factored matrix to be reset
7842 
7843    Notes:
7844    This routine should be used only with factored matrices formed by in-place
7845    factorization via ILU(0) (or by in-place LU factorization for the MATSEQDENSE
7846    format).  This option can save memory, for example, when solving nonlinear
7847    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7848    ILU(0) preconditioner.
7849 
7850    Note that one can specify in-place ILU(0) factorization by calling
7851 .vb
7852      PCType(pc,PCILU);
7853      PCFactorSeUseInPlace(pc);
7854 .ve
7855    or by using the options -pc_type ilu -pc_factor_in_place
7856 
7857    In-place factorization ILU(0) can also be used as a local
7858    solver for the blocks within the block Jacobi or additive Schwarz
7859    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7860    for details on setting local solver options.
7861 
7862    Most users should employ the simplified KSP interface for linear solvers
7863    instead of working directly with matrix algebra routines such as this.
7864    See, e.g., KSPCreate().
7865 
7866    Level: developer
7867 
7868 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7869 
7870 @*/
7871 PetscErrorCode MatSetUnfactored(Mat mat) {
7872   PetscFunctionBegin;
7873   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7874   PetscValidType(mat, 1);
7875   MatCheckPreallocated(mat, 1);
7876   mat->factortype = MAT_FACTOR_NONE;
7877   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
7878   PetscUseTypeMethod(mat, setunfactored);
7879   PetscFunctionReturn(0);
7880 }
7881 
7882 /*MC
7883     MatDenseGetArrayF90 - Accesses a matrix array from Fortran90.
7884 
7885     Synopsis:
7886     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7887 
7888     Not collective
7889 
7890     Input Parameter:
7891 .   x - matrix
7892 
7893     Output Parameters:
7894 +   xx_v - the Fortran90 pointer to the array
7895 -   ierr - error code
7896 
7897     Example of Usage:
7898 .vb
7899       PetscScalar, pointer xx_v(:,:)
7900       ....
7901       call MatDenseGetArrayF90(x,xx_v,ierr)
7902       a = xx_v(3)
7903       call MatDenseRestoreArrayF90(x,xx_v,ierr)
7904 .ve
7905 
7906     Level: advanced
7907 
7908 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
7909 
7910 M*/
7911 
7912 /*MC
7913     MatDenseRestoreArrayF90 - Restores a matrix array that has been
7914     accessed with MatDenseGetArrayF90().
7915 
7916     Synopsis:
7917     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7918 
7919     Not collective
7920 
7921     Input Parameters:
7922 +   x - matrix
7923 -   xx_v - the Fortran90 pointer to the array
7924 
7925     Output Parameter:
7926 .   ierr - error code
7927 
7928     Example of Usage:
7929 .vb
7930        PetscScalar, pointer xx_v(:,:)
7931        ....
7932        call MatDenseGetArrayF90(x,xx_v,ierr)
7933        a = xx_v(3)
7934        call MatDenseRestoreArrayF90(x,xx_v,ierr)
7935 .ve
7936 
7937     Level: advanced
7938 
7939 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
7940 
7941 M*/
7942 
7943 /*MC
7944     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran90.
7945 
7946     Synopsis:
7947     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7948 
7949     Not collective
7950 
7951     Input Parameter:
7952 .   x - matrix
7953 
7954     Output Parameters:
7955 +   xx_v - the Fortran90 pointer to the array
7956 -   ierr - error code
7957 
7958     Example of Usage:
7959 .vb
7960       PetscScalar, pointer xx_v(:)
7961       ....
7962       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7963       a = xx_v(3)
7964       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7965 .ve
7966 
7967     Level: advanced
7968 
7969 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
7970 
7971 M*/
7972 
7973 /*MC
7974     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
7975     accessed with MatSeqAIJGetArrayF90().
7976 
7977     Synopsis:
7978     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7979 
7980     Not collective
7981 
7982     Input Parameters:
7983 +   x - matrix
7984 -   xx_v - the Fortran90 pointer to the array
7985 
7986     Output Parameter:
7987 .   ierr - error code
7988 
7989     Example of Usage:
7990 .vb
7991        PetscScalar, pointer xx_v(:)
7992        ....
7993        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7994        a = xx_v(3)
7995        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7996 .ve
7997 
7998     Level: advanced
7999 
8000 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8001 
8002 M*/
8003 
8004 /*@
8005     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8006                       as the original matrix.
8007 
8008     Collective on Mat
8009 
8010     Input Parameters:
8011 +   mat - the original matrix
8012 .   isrow - parallel IS containing the rows this processor should obtain
8013 .   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.
8014 -   cll - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
8015 
8016     Output Parameter:
8017 .   newmat - the new submatrix, of the same type as the old
8018 
8019     Level: advanced
8020 
8021     Notes:
8022     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8023 
8024     Some matrix types place restrictions on the row and column indices, such
8025     as that they be sorted or that they be equal to each other.
8026 
8027     The index sets may not have duplicate entries.
8028 
8029       The first time this is called you should use a cll of MAT_INITIAL_MATRIX,
8030    the MatCreateSubMatrix() routine will create the newmat for you. Any additional calls
8031    to this routine with a mat of the same nonzero structure and with a call of MAT_REUSE_MATRIX
8032    will reuse the matrix generated the first time.  You should call MatDestroy() on newmat when
8033    you are finished using it.
8034 
8035     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8036     the input matrix.
8037 
8038     If iscol is NULL then all columns are obtained (not supported in Fortran).
8039 
8040    Example usage:
8041    Consider the following 8x8 matrix with 34 non-zero values, that is
8042    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8043    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8044    as follows:
8045 
8046 .vb
8047             1  2  0  |  0  3  0  |  0  4
8048     Proc0   0  5  6  |  7  0  0  |  8  0
8049             9  0 10  | 11  0  0  | 12  0
8050     -------------------------------------
8051            13  0 14  | 15 16 17  |  0  0
8052     Proc1   0 18  0  | 19 20 21  |  0  0
8053             0  0  0  | 22 23  0  | 24  0
8054     -------------------------------------
8055     Proc2  25 26 27  |  0  0 28  | 29  0
8056            30  0  0  | 31 32 33  |  0 34
8057 .ve
8058 
8059     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8060 
8061 .vb
8062             2  0  |  0  3  0  |  0
8063     Proc0   5  6  |  7  0  0  |  8
8064     -------------------------------
8065     Proc1  18  0  | 19 20 21  |  0
8066     -------------------------------
8067     Proc2  26 27  |  0  0 28  | 29
8068             0  0  | 31 32 33  |  0
8069 .ve
8070 
8071 .seealso: `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8072 @*/
8073 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) {
8074   PetscMPIInt size;
8075   Mat        *local;
8076   IS          iscoltmp;
8077   PetscBool   flg;
8078 
8079   PetscFunctionBegin;
8080   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8081   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8082   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8083   PetscValidPointer(newmat, 5);
8084   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8085   PetscValidType(mat, 1);
8086   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8087   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8088 
8089   MatCheckPreallocated(mat, 1);
8090   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8091 
8092   if (!iscol || isrow == iscol) {
8093     PetscBool   stride;
8094     PetscMPIInt grabentirematrix = 0, grab;
8095     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8096     if (stride) {
8097       PetscInt first, step, n, rstart, rend;
8098       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8099       if (step == 1) {
8100         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8101         if (rstart == first) {
8102           PetscCall(ISGetLocalSize(isrow, &n));
8103           if (n == rend - rstart) { grabentirematrix = 1; }
8104         }
8105       }
8106     }
8107     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8108     if (grab) {
8109       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8110       if (cll == MAT_INITIAL_MATRIX) {
8111         *newmat = mat;
8112         PetscCall(PetscObjectReference((PetscObject)mat));
8113       }
8114       PetscFunctionReturn(0);
8115     }
8116   }
8117 
8118   if (!iscol) {
8119     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8120   } else {
8121     iscoltmp = iscol;
8122   }
8123 
8124   /* if original matrix is on just one processor then use submatrix generated */
8125   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8126     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8127     goto setproperties;
8128   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8129     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8130     *newmat = *local;
8131     PetscCall(PetscFree(local));
8132     goto setproperties;
8133   } else if (!mat->ops->createsubmatrix) {
8134     /* Create a new matrix type that implements the operation using the full matrix */
8135     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8136     switch (cll) {
8137     case MAT_INITIAL_MATRIX: PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); break;
8138     case MAT_REUSE_MATRIX: PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); break;
8139     default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8140     }
8141     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8142     goto setproperties;
8143   }
8144 
8145   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8146   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8147   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8148 
8149 setproperties:
8150   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8151   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8152   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8153   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8154   PetscFunctionReturn(0);
8155 }
8156 
8157 /*@
8158    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8159 
8160    Not Collective
8161 
8162    Input Parameters:
8163 +  A - the matrix we wish to propagate options from
8164 -  B - the matrix we wish to propagate options to
8165 
8166    Level: beginner
8167 
8168    Notes:
8169    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8170 
8171 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8172 @*/
8173 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) {
8174   PetscFunctionBegin;
8175   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8176   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8177   B->symmetry_eternal            = A->symmetry_eternal;
8178   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8179   B->symmetric                   = A->symmetric;
8180   B->structurally_symmetric      = A->structurally_symmetric;
8181   B->spd                         = A->spd;
8182   B->hermitian                   = A->hermitian;
8183   PetscFunctionReturn(0);
8184 }
8185 
8186 /*@
8187    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8188    used during the assembly process to store values that belong to
8189    other processors.
8190 
8191    Not Collective
8192 
8193    Input Parameters:
8194 +  mat   - the matrix
8195 .  size  - the initial size of the stash.
8196 -  bsize - the initial size of the block-stash(if used).
8197 
8198    Options Database Keys:
8199 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8200 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8201 
8202    Level: intermediate
8203 
8204    Notes:
8205      The block-stash is used for values set with MatSetValuesBlocked() while
8206      the stash is used for values set with MatSetValues()
8207 
8208      Run with the option -info and look for output of the form
8209      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8210      to determine the appropriate value, MM, to use for size and
8211      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8212      to determine the value, BMM to use for bsize
8213 
8214 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8215 
8216 @*/
8217 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) {
8218   PetscFunctionBegin;
8219   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8220   PetscValidType(mat, 1);
8221   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8222   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8223   PetscFunctionReturn(0);
8224 }
8225 
8226 /*@
8227    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8228      the matrix
8229 
8230    Neighbor-wise Collective on Mat
8231 
8232    Input Parameters:
8233 +  mat   - the matrix
8234 .  x,y - the vectors
8235 -  w - where the result is stored
8236 
8237    Level: intermediate
8238 
8239    Notes:
8240     w may be the same vector as y.
8241 
8242     This allows one to use either the restriction or interpolation (its transpose)
8243     matrix to do the interpolation
8244 
8245 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8246 
8247 @*/
8248 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) {
8249   PetscInt M, N, Ny;
8250 
8251   PetscFunctionBegin;
8252   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8253   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8254   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8255   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8256   PetscCall(MatGetSize(A, &M, &N));
8257   PetscCall(VecGetSize(y, &Ny));
8258   if (M == Ny) {
8259     PetscCall(MatMultAdd(A, x, y, w));
8260   } else {
8261     PetscCall(MatMultTransposeAdd(A, x, y, w));
8262   }
8263   PetscFunctionReturn(0);
8264 }
8265 
8266 /*@
8267    MatInterpolate - y = A*x or A'*x depending on the shape of
8268      the matrix
8269 
8270    Neighbor-wise Collective on Mat
8271 
8272    Input Parameters:
8273 +  mat   - the matrix
8274 -  x,y - the vectors
8275 
8276    Level: intermediate
8277 
8278    Notes:
8279     This allows one to use either the restriction or interpolation (its transpose)
8280     matrix to do the interpolation
8281 
8282 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`
8283 
8284 @*/
8285 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) {
8286   PetscInt M, N, Ny;
8287 
8288   PetscFunctionBegin;
8289   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8290   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8291   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8292   PetscCall(MatGetSize(A, &M, &N));
8293   PetscCall(VecGetSize(y, &Ny));
8294   if (M == Ny) {
8295     PetscCall(MatMult(A, x, y));
8296   } else {
8297     PetscCall(MatMultTranspose(A, x, y));
8298   }
8299   PetscFunctionReturn(0);
8300 }
8301 
8302 /*@
8303    MatRestrict - y = A*x or A'*x
8304 
8305    Neighbor-wise Collective on Mat
8306 
8307    Input Parameters:
8308 +  mat   - the matrix
8309 -  x,y - the vectors
8310 
8311    Level: intermediate
8312 
8313    Notes:
8314     This allows one to use either the restriction or interpolation (its transpose)
8315     matrix to do the restriction
8316 
8317 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`
8318 
8319 @*/
8320 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) {
8321   PetscInt M, N, Ny;
8322 
8323   PetscFunctionBegin;
8324   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8325   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8326   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8327   PetscCall(MatGetSize(A, &M, &N));
8328   PetscCall(VecGetSize(y, &Ny));
8329   if (M == Ny) {
8330     PetscCall(MatMult(A, x, y));
8331   } else {
8332     PetscCall(MatMultTranspose(A, x, y));
8333   }
8334   PetscFunctionReturn(0);
8335 }
8336 
8337 /*@
8338    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8339 
8340    Neighbor-wise Collective on Mat
8341 
8342    Input Parameters:
8343 +  mat   - the matrix
8344 -  w, x - the input dense matrices
8345 
8346    Output Parameters:
8347 .  y - the output dense matrix
8348 
8349    Level: intermediate
8350 
8351    Notes:
8352     This allows one to use either the restriction or interpolation (its transpose)
8353     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8354     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8355 
8356 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`
8357 
8358 @*/
8359 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) {
8360   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8361   PetscBool trans = PETSC_TRUE;
8362   MatReuse  reuse = MAT_INITIAL_MATRIX;
8363 
8364   PetscFunctionBegin;
8365   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8366   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8367   PetscValidType(x, 2);
8368   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8369   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8370   PetscCall(MatGetSize(A, &M, &N));
8371   PetscCall(MatGetSize(x, &Mx, &Nx));
8372   if (N == Mx) trans = PETSC_FALSE;
8373   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);
8374   Mo = trans ? N : M;
8375   if (*y) {
8376     PetscCall(MatGetSize(*y, &My, &Ny));
8377     if (Mo == My && Nx == Ny) {
8378       reuse = MAT_REUSE_MATRIX;
8379     } else {
8380       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);
8381       PetscCall(MatDestroy(y));
8382     }
8383   }
8384 
8385   if (w && *y == w) { /* this is to minimize changes in PCMG */
8386     PetscBool flg;
8387 
8388     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8389     if (w) {
8390       PetscInt My, Ny, Mw, Nw;
8391 
8392       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8393       PetscCall(MatGetSize(*y, &My, &Ny));
8394       PetscCall(MatGetSize(w, &Mw, &Nw));
8395       if (!flg || My != Mw || Ny != Nw) w = NULL;
8396     }
8397     if (!w) {
8398       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8399       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8400       PetscCall(PetscLogObjectParent((PetscObject)*y, (PetscObject)w));
8401       PetscCall(PetscObjectDereference((PetscObject)w));
8402     } else {
8403       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8404     }
8405   }
8406   if (!trans) {
8407     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8408   } else {
8409     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8410   }
8411   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8412   PetscFunctionReturn(0);
8413 }
8414 
8415 /*@
8416    MatMatInterpolate - Y = A*X or A'*X
8417 
8418    Neighbor-wise Collective on Mat
8419 
8420    Input Parameters:
8421 +  mat   - the matrix
8422 -  x - the input dense matrix
8423 
8424    Output Parameters:
8425 .  y - the output dense matrix
8426 
8427    Level: intermediate
8428 
8429    Notes:
8430     This allows one to use either the restriction or interpolation (its transpose)
8431     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8432     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8433 
8434 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`
8435 
8436 @*/
8437 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) {
8438   PetscFunctionBegin;
8439   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8440   PetscFunctionReturn(0);
8441 }
8442 
8443 /*@
8444    MatMatRestrict - Y = A*X or A'*X
8445 
8446    Neighbor-wise Collective on Mat
8447 
8448    Input Parameters:
8449 +  mat   - the matrix
8450 -  x - the input dense matrix
8451 
8452    Output Parameters:
8453 .  y - the output dense matrix
8454 
8455    Level: intermediate
8456 
8457    Notes:
8458     This allows one to use either the restriction or interpolation (its transpose)
8459     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8460     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8461 
8462 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`
8463 @*/
8464 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) {
8465   PetscFunctionBegin;
8466   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8467   PetscFunctionReturn(0);
8468 }
8469 
8470 /*@
8471    MatGetNullSpace - retrieves the null space of a matrix.
8472 
8473    Logically Collective on Mat
8474 
8475    Input Parameters:
8476 +  mat - the matrix
8477 -  nullsp - the null space object
8478 
8479    Level: developer
8480 
8481 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`
8482 @*/
8483 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) {
8484   PetscFunctionBegin;
8485   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8486   PetscValidPointer(nullsp, 2);
8487   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8488   PetscFunctionReturn(0);
8489 }
8490 
8491 /*@
8492    MatSetNullSpace - attaches a null space to a matrix.
8493 
8494    Logically Collective on Mat
8495 
8496    Input Parameters:
8497 +  mat - the matrix
8498 -  nullsp - the null space object
8499 
8500    Level: advanced
8501 
8502    Notes:
8503       This null space is used by the KSP linear solvers to solve singular systems.
8504 
8505       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
8506 
8507       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
8508       to zero but the linear system will still be solved in a least squares sense.
8509 
8510       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8511    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).
8512    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
8513    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
8514    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).
8515    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8516 
8517     If the matrix is known to be symmetric because it is an SBAIJ matrix or one as called MatSetOption(mat,MAT_SYMMETRIC or MAT_SYMMETRY_ETERNAL,PETSC_TRUE); this
8518     routine also automatically calls MatSetTransposeNullSpace().
8519 
8520     The user should call `MatNullSpaceDestroy()`.
8521 
8522 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8523           `KSPSetPCSide()`
8524 @*/
8525 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) {
8526   PetscFunctionBegin;
8527   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8528   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8529   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8530   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8531   mat->nullsp = nullsp;
8532   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8533   PetscFunctionReturn(0);
8534 }
8535 
8536 /*@
8537    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8538 
8539    Logically Collective on Mat
8540 
8541    Input Parameters:
8542 +  mat - the matrix
8543 -  nullsp - the null space object
8544 
8545    Level: developer
8546 
8547 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8548 @*/
8549 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) {
8550   PetscFunctionBegin;
8551   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8552   PetscValidType(mat, 1);
8553   PetscValidPointer(nullsp, 2);
8554   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8555   PetscFunctionReturn(0);
8556 }
8557 
8558 /*@
8559    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8560 
8561    Logically Collective on Mat
8562 
8563    Input Parameters:
8564 +  mat - the matrix
8565 -  nullsp - the null space object
8566 
8567    Level: advanced
8568 
8569    Notes:
8570       This allows solving singular linear systems defined by the transpose of the matrix using KSP solvers with left preconditioning.
8571 
8572       See MatSetNullSpace()
8573 
8574 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8575 @*/
8576 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) {
8577   PetscFunctionBegin;
8578   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8579   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8580   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8581   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8582   mat->transnullsp = nullsp;
8583   PetscFunctionReturn(0);
8584 }
8585 
8586 /*@
8587    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8588         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8589 
8590    Logically Collective on Mat
8591 
8592    Input Parameters:
8593 +  mat - the matrix
8594 -  nullsp - the null space object
8595 
8596    Level: advanced
8597 
8598    Notes:
8599       Overwrites any previous near null space that may have been attached
8600 
8601       You can remove the null space by calling this routine with an nullsp of NULL
8602 
8603 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8604 @*/
8605 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) {
8606   PetscFunctionBegin;
8607   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8608   PetscValidType(mat, 1);
8609   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8610   MatCheckPreallocated(mat, 1);
8611   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8612   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8613   mat->nearnullsp = nullsp;
8614   PetscFunctionReturn(0);
8615 }
8616 
8617 /*@
8618    MatGetNearNullSpace - Get null space attached with MatSetNearNullSpace()
8619 
8620    Not Collective
8621 
8622    Input Parameter:
8623 .  mat - the matrix
8624 
8625    Output Parameter:
8626 .  nullsp - the null space object, NULL if not set
8627 
8628    Level: developer
8629 
8630 .seealso: `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8631 @*/
8632 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) {
8633   PetscFunctionBegin;
8634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8635   PetscValidType(mat, 1);
8636   PetscValidPointer(nullsp, 2);
8637   MatCheckPreallocated(mat, 1);
8638   *nullsp = mat->nearnullsp;
8639   PetscFunctionReturn(0);
8640 }
8641 
8642 /*@C
8643    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8644 
8645    Collective on Mat
8646 
8647    Input Parameters:
8648 +  mat - the matrix
8649 .  row - row/column permutation
8650 .  fill - expected fill factor >= 1.0
8651 -  level - level of fill, for ICC(k)
8652 
8653    Notes:
8654    Probably really in-place only when level of fill is zero, otherwise allocates
8655    new space to store factored matrix and deletes previous memory.
8656 
8657    Most users should employ the simplified KSP interface for linear solvers
8658    instead of working directly with matrix algebra routines such as this.
8659    See, e.g., KSPCreate().
8660 
8661    Level: developer
8662 
8663 .seealso: `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8664 
8665     Developer Note: fortran interface is not autogenerated as the f90
8666     interface definition cannot be generated correctly [due to MatFactorInfo]
8667 
8668 @*/
8669 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) {
8670   PetscFunctionBegin;
8671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8672   PetscValidType(mat, 1);
8673   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8674   PetscValidPointer(info, 3);
8675   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8676   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8677   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8678   MatCheckPreallocated(mat, 1);
8679   PetscUseTypeMethod(mat, iccfactor, row, info);
8680   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8681   PetscFunctionReturn(0);
8682 }
8683 
8684 /*@
8685    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8686          ghosted ones.
8687 
8688    Not Collective
8689 
8690    Input Parameters:
8691 +  mat - the matrix
8692 -  diag - the diagonal values, including ghost ones
8693 
8694    Level: developer
8695 
8696    Notes:
8697     Works only for MPIAIJ and MPIBAIJ matrices
8698 
8699 .seealso: `MatDiagonalScale()`
8700 @*/
8701 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) {
8702   PetscMPIInt size;
8703 
8704   PetscFunctionBegin;
8705   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8706   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8707   PetscValidType(mat, 1);
8708 
8709   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8710   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8711   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8712   if (size == 1) {
8713     PetscInt n, m;
8714     PetscCall(VecGetSize(diag, &n));
8715     PetscCall(MatGetSize(mat, NULL, &m));
8716     if (m == n) {
8717       PetscCall(MatDiagonalScale(mat, NULL, diag));
8718     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8719   } else {
8720     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8721   }
8722   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
8723   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8724   PetscFunctionReturn(0);
8725 }
8726 
8727 /*@
8728    MatGetInertia - Gets the inertia from a factored matrix
8729 
8730    Collective on Mat
8731 
8732    Input Parameter:
8733 .  mat - the matrix
8734 
8735    Output Parameters:
8736 +   nneg - number of negative eigenvalues
8737 .   nzero - number of zero eigenvalues
8738 -   npos - number of positive eigenvalues
8739 
8740    Level: advanced
8741 
8742    Notes:
8743     Matrix must have been factored by MatCholeskyFactor()
8744 
8745 @*/
8746 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) {
8747   PetscFunctionBegin;
8748   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8749   PetscValidType(mat, 1);
8750   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8751   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
8752   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8753   PetscFunctionReturn(0);
8754 }
8755 
8756 /* ----------------------------------------------------------------*/
8757 /*@C
8758    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8759 
8760    Neighbor-wise Collective on Mats
8761 
8762    Input Parameters:
8763 +  mat - the factored matrix
8764 -  b - the right-hand-side vectors
8765 
8766    Output Parameter:
8767 .  x - the result vectors
8768 
8769    Notes:
8770    The vectors b and x cannot be the same.  I.e., one cannot
8771    call MatSolves(A,x,x).
8772 
8773    Notes:
8774    Most users should employ the simplified KSP interface for linear solvers
8775    instead of working directly with matrix algebra routines such as this.
8776    See, e.g., KSPCreate().
8777 
8778    Level: developer
8779 
8780 .seealso: `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8781 @*/
8782 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) {
8783   PetscFunctionBegin;
8784   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8785   PetscValidType(mat, 1);
8786   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
8787   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8788   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
8789 
8790   MatCheckPreallocated(mat, 1);
8791   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
8792   PetscUseTypeMethod(mat, solves, b, x);
8793   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
8794   PetscFunctionReturn(0);
8795 }
8796 
8797 /*@
8798    MatIsSymmetric - Test whether a matrix is symmetric
8799 
8800    Collective on Mat
8801 
8802    Input Parameters:
8803 +  A - the matrix to test
8804 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8805 
8806    Output Parameters:
8807 .  flg - the result
8808 
8809    Notes:
8810     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
8811 
8812     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
8813 
8814    Level: intermediate
8815 
8816 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`
8817 @*/
8818 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) {
8819   PetscFunctionBegin;
8820   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8821   PetscValidBoolPointer(flg, 3);
8822 
8823   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8824   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8825   else {
8826     if (!A->ops->issymmetric) {
8827       MatType mattype;
8828       PetscCall(MatGetType(A, &mattype));
8829       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8830     }
8831     PetscUseTypeMethod(A, issymmetric, tol, flg);
8832     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
8833   }
8834   PetscFunctionReturn(0);
8835 }
8836 
8837 /*@
8838    MatIsHermitian - Test whether a matrix is Hermitian
8839 
8840    Collective on Mat
8841 
8842    Input Parameters:
8843 +  A - the matrix to test
8844 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8845 
8846    Output Parameters:
8847 .  flg - the result
8848 
8849    Level: intermediate
8850 
8851    Notes:
8852     For real numbers MatIsSymmetric() and MatIsHermitian() return identical results
8853 
8854     If the matrix does not yet know if it is hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
8855 
8856 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8857           `MatIsSymmetricKnown()`, `MatIsSymmetric()`
8858 @*/
8859 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) {
8860   PetscFunctionBegin;
8861   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8862   PetscValidBoolPointer(flg, 3);
8863 
8864   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8865   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8866   else {
8867     if (!A->ops->ishermitian) {
8868       MatType mattype;
8869       PetscCall(MatGetType(A, &mattype));
8870       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8871     }
8872     PetscUseTypeMethod(A, ishermitian, tol, flg);
8873     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
8874   }
8875   PetscFunctionReturn(0);
8876 }
8877 
8878 /*@
8879    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
8880 
8881    Not Collective
8882 
8883    Input Parameter:
8884 .  A - the matrix to check
8885 
8886    Output Parameters:
8887 +  set - PETSC_TRUE if the matrix knows its symmetry state (this tells you if the next flag is valid)
8888 -  flg - the result (only valid if set is PETSC_TRUE)
8889 
8890    Level: advanced
8891 
8892    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsSymmetric()
8893          if you want it explicitly checked
8894 
8895 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8896 @*/
8897 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) {
8898   PetscFunctionBegin;
8899   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8900   PetscValidBoolPointer(set, 2);
8901   PetscValidBoolPointer(flg, 3);
8902   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8903     *set = PETSC_TRUE;
8904     *flg = PetscBool3ToBool(A->symmetric);
8905   } else {
8906     *set = PETSC_FALSE;
8907   }
8908   PetscFunctionReturn(0);
8909 }
8910 
8911 /*@
8912    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
8913 
8914    Not Collective
8915 
8916    Input Parameter:
8917 .  A - the matrix to check
8918 
8919    Output Parameters:
8920 +  set - PETSC_TRUE if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8921 -  flg - the result (only valid if set is PETSC_TRUE)
8922 
8923    Level: advanced
8924 
8925    Note:
8926    Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE).
8927 
8928 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8929 @*/
8930 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) {
8931   PetscFunctionBegin;
8932   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8933   PetscValidBoolPointer(set, 2);
8934   PetscValidBoolPointer(flg, 3);
8935   if (A->spd != PETSC_BOOL3_UNKNOWN) {
8936     *set = PETSC_TRUE;
8937     *flg = PetscBool3ToBool(A->spd);
8938   } else {
8939     *set = PETSC_FALSE;
8940   }
8941   PetscFunctionReturn(0);
8942 }
8943 
8944 /*@
8945    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
8946 
8947    Not Collective
8948 
8949    Input Parameter:
8950 .  A - the matrix to check
8951 
8952    Output Parameters:
8953 +  set - PETSC_TRUE if the matrix knows its Hermitian state (this tells you if the next flag is valid)
8954 -  flg - the result (only valid if set is PETSC_TRUE)
8955 
8956    Level: advanced
8957 
8958    Note: Does not check the matrix values directly, so this may return unknown (set = PETSC_FALSE). Use MatIsHermitian()
8959          if you want it explicitly checked
8960 
8961 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
8962 @*/
8963 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) {
8964   PetscFunctionBegin;
8965   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8966   PetscValidBoolPointer(set, 2);
8967   PetscValidBoolPointer(flg, 3);
8968   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
8969     *set = PETSC_TRUE;
8970     *flg = PetscBool3ToBool(A->hermitian);
8971   } else {
8972     *set = PETSC_FALSE;
8973   }
8974   PetscFunctionReturn(0);
8975 }
8976 
8977 /*@
8978    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
8979 
8980    Collective on Mat
8981 
8982    Input Parameter:
8983 .  A - the matrix to test
8984 
8985    Output Parameters:
8986 .  flg - the result
8987 
8988    Notes:
8989       If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
8990 
8991    Level: intermediate
8992 
8993 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
8994 @*/
8995 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) {
8996   PetscFunctionBegin;
8997   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8998   PetscValidBoolPointer(flg, 2);
8999   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9000     *flg = PetscBool3ToBool(A->structurally_symmetric);
9001   } else {
9002     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9003     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9004   }
9005   PetscFunctionReturn(0);
9006 }
9007 
9008 /*@
9009    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9010 
9011    Not Collective
9012 
9013    Input Parameter:
9014 .  A - the matrix to check
9015 
9016    Output Parameters:
9017 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9018 -  flg - the result (only valid if set is PETSC_TRUE)
9019 
9020    Level: advanced
9021 
9022 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9023 @*/
9024 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) {
9025   PetscFunctionBegin;
9026   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9027   PetscValidBoolPointer(set, 2);
9028   PetscValidBoolPointer(flg, 3);
9029   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9030     *set = PETSC_TRUE;
9031     *flg = PetscBool3ToBool(A->structurally_symmetric);
9032   } else {
9033     *set = PETSC_FALSE;
9034   }
9035   PetscFunctionReturn(0);
9036 }
9037 
9038 /*@
9039    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9040        to be communicated to other processors during the MatAssemblyBegin/End() process
9041 
9042     Not collective
9043 
9044    Input Parameter:
9045 .   vec - the vector
9046 
9047    Output Parameters:
9048 +   nstash   - the size of the stash
9049 .   reallocs - the number of additional mallocs incurred.
9050 .   bnstash   - the size of the block stash
9051 -   breallocs - the number of additional mallocs incurred.in the block stash
9052 
9053    Level: advanced
9054 
9055 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9056 
9057 @*/
9058 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) {
9059   PetscFunctionBegin;
9060   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9061   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9062   PetscFunctionReturn(0);
9063 }
9064 
9065 /*@C
9066    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9067      parallel layout
9068 
9069    Collective on Mat
9070 
9071    Input Parameter:
9072 .  mat - the matrix
9073 
9074    Output Parameters:
9075 +   right - (optional) vector that the matrix can be multiplied against
9076 -   left - (optional) vector that the matrix vector product can be stored in
9077 
9078    Notes:
9079     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().
9080 
9081   Notes:
9082     These are new vectors which are not owned by the Mat, they should be destroyed in VecDestroy() when no longer needed
9083 
9084   Level: advanced
9085 
9086 .seealso: `MatCreate()`, `VecDestroy()`
9087 @*/
9088 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) {
9089   PetscFunctionBegin;
9090   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9091   PetscValidType(mat, 1);
9092   if (mat->ops->getvecs) {
9093     PetscUseTypeMethod(mat, getvecs, right, left);
9094   } else {
9095     PetscInt rbs, cbs;
9096     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9097     if (right) {
9098       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9099       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9100       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9101       PetscCall(VecSetBlockSize(*right, cbs));
9102       PetscCall(VecSetType(*right, mat->defaultvectype));
9103 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9104       if (mat->boundtocpu && mat->bindingpropagates) {
9105         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9106         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9107       }
9108 #endif
9109       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9110     }
9111     if (left) {
9112       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9113       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9114       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9115       PetscCall(VecSetBlockSize(*left, rbs));
9116       PetscCall(VecSetType(*left, mat->defaultvectype));
9117 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9118       if (mat->boundtocpu && mat->bindingpropagates) {
9119         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9120         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9121       }
9122 #endif
9123       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9124     }
9125   }
9126   PetscFunctionReturn(0);
9127 }
9128 
9129 /*@C
9130    MatFactorInfoInitialize - Initializes a MatFactorInfo data structure
9131      with default values.
9132 
9133    Not Collective
9134 
9135    Input Parameters:
9136 .    info - the MatFactorInfo data structure
9137 
9138    Notes:
9139     The solvers are generally used through the KSP and PC objects, for example
9140           PCLU, PCILU, PCCHOLESKY, PCICC
9141 
9142    Level: developer
9143 
9144 .seealso: `MatFactorInfo`
9145 
9146     Developer Note: fortran interface is not autogenerated as the f90
9147     interface definition cannot be generated correctly [due to MatFactorInfo]
9148 
9149 @*/
9150 
9151 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) {
9152   PetscFunctionBegin;
9153   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9154   PetscFunctionReturn(0);
9155 }
9156 
9157 /*@
9158    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9159 
9160    Collective on Mat
9161 
9162    Input Parameters:
9163 +  mat - the factored matrix
9164 -  is - the index set defining the Schur indices (0-based)
9165 
9166    Notes:
9167     Call MatFactorSolveSchurComplement() or MatFactorSolveSchurComplementTranspose() after this call to solve a Schur complement system.
9168 
9169    You can call MatFactorGetSchurComplement() or MatFactorCreateSchurComplement() after this call.
9170 
9171    Level: developer
9172 
9173 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9174           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`
9175 
9176 @*/
9177 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) {
9178   PetscErrorCode (*f)(Mat, IS);
9179 
9180   PetscFunctionBegin;
9181   PetscValidType(mat, 1);
9182   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9183   PetscValidType(is, 2);
9184   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9185   PetscCheckSameComm(mat, 1, is, 2);
9186   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9187   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9188   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9189   PetscCall(MatDestroy(&mat->schur));
9190   PetscCall((*f)(mat, is));
9191   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9192   PetscFunctionReturn(0);
9193 }
9194 
9195 /*@
9196   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9197 
9198    Logically Collective on Mat
9199 
9200    Input Parameters:
9201 +  F - the factored matrix obtained by calling MatGetFactor() from PETSc-MUMPS interface
9202 .  S - location where to return the Schur complement, can be NULL
9203 -  status - the status of the Schur complement matrix, can be NULL
9204 
9205    Notes:
9206    You must call MatFactorSetSchurIS() before calling this routine.
9207 
9208    The routine provides a copy of the Schur matrix stored within the solver data structures.
9209    The caller must destroy the object when it is no longer needed.
9210    If MatFactorInvertSchurComplement() has been called, the routine gets back the inverse.
9211 
9212    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)
9213 
9214    Developer Notes:
9215     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9216    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9217 
9218    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9219 
9220    Level: advanced
9221 
9222    References:
9223 
9224 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`
9225 @*/
9226 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) {
9227   PetscFunctionBegin;
9228   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9229   if (S) PetscValidPointer(S, 2);
9230   if (status) PetscValidPointer(status, 3);
9231   if (S) {
9232     PetscErrorCode (*f)(Mat, Mat *);
9233 
9234     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9235     if (f) {
9236       PetscCall((*f)(F, S));
9237     } else {
9238       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9239     }
9240   }
9241   if (status) *status = F->schur_status;
9242   PetscFunctionReturn(0);
9243 }
9244 
9245 /*@
9246   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9247 
9248    Logically Collective on Mat
9249 
9250    Input Parameters:
9251 +  F - the factored matrix obtained by calling MatGetFactor()
9252 .  *S - location where to return the Schur complement, can be NULL
9253 -  status - the status of the Schur complement matrix, can be NULL
9254 
9255    Notes:
9256    You must call MatFactorSetSchurIS() before calling this routine.
9257 
9258    Schur complement mode is currently implemented for sequential matrices.
9259    The routine returns a the Schur Complement stored within the data strutures of the solver.
9260    If MatFactorInvertSchurComplement() has previously been called, the returned matrix is actually the inverse of the Schur complement.
9261    The returned matrix should not be destroyed; the caller should call MatFactorRestoreSchurComplement() when the object is no longer needed.
9262 
9263    Use MatFactorCreateSchurComplement() to create a copy of the Schur complement matrix that is within a factored matrix
9264 
9265    See MatCreateSchurComplement() or MatGetSchurComplement() for ways to create virtual or approximate Schur complements.
9266 
9267    Level: advanced
9268 
9269    References:
9270 
9271 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9272 @*/
9273 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) {
9274   PetscFunctionBegin;
9275   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9276   if (S) PetscValidPointer(S, 2);
9277   if (status) PetscValidPointer(status, 3);
9278   if (S) *S = F->schur;
9279   if (status) *status = F->schur_status;
9280   PetscFunctionReturn(0);
9281 }
9282 
9283 /*@
9284   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to MatFactorGetSchurComplement
9285 
9286    Logically Collective on Mat
9287 
9288    Input Parameters:
9289 +  F - the factored matrix obtained by calling MatGetFactor()
9290 .  *S - location where the Schur complement is stored
9291 -  status - the status of the Schur complement matrix (see MatFactorSchurStatus)
9292 
9293    Notes:
9294 
9295    Level: advanced
9296 
9297    References:
9298 
9299 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9300 @*/
9301 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) {
9302   PetscFunctionBegin;
9303   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9304   if (S) {
9305     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9306     *S = NULL;
9307   }
9308   F->schur_status = status;
9309   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9310   PetscFunctionReturn(0);
9311 }
9312 
9313 /*@
9314   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9315 
9316    Logically Collective on Mat
9317 
9318    Input Parameters:
9319 +  F - the factored matrix obtained by calling MatGetFactor()
9320 .  rhs - location where the right hand side of the Schur complement system is stored
9321 -  sol - location where the solution of the Schur complement system has to be returned
9322 
9323    Notes:
9324    The sizes of the vectors should match the size of the Schur complement
9325 
9326    Must be called after MatFactorSetSchurIS()
9327 
9328    Level: advanced
9329 
9330    References:
9331 
9332 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9333 @*/
9334 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) {
9335   PetscFunctionBegin;
9336   PetscValidType(F, 1);
9337   PetscValidType(rhs, 2);
9338   PetscValidType(sol, 3);
9339   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9340   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9341   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9342   PetscCheckSameComm(F, 1, rhs, 2);
9343   PetscCheckSameComm(F, 1, sol, 3);
9344   PetscCall(MatFactorFactorizeSchurComplement(F));
9345   switch (F->schur_status) {
9346   case MAT_FACTOR_SCHUR_FACTORED: PetscCall(MatSolveTranspose(F->schur, rhs, sol)); break;
9347   case MAT_FACTOR_SCHUR_INVERTED: PetscCall(MatMultTranspose(F->schur, rhs, sol)); break;
9348   default: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9349   }
9350   PetscFunctionReturn(0);
9351 }
9352 
9353 /*@
9354   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9355 
9356    Logically Collective on Mat
9357 
9358    Input Parameters:
9359 +  F - the factored matrix obtained by calling MatGetFactor()
9360 .  rhs - location where the right hand side of the Schur complement system is stored
9361 -  sol - location where the solution of the Schur complement system has to be returned
9362 
9363    Notes:
9364    The sizes of the vectors should match the size of the Schur complement
9365 
9366    Must be called after MatFactorSetSchurIS()
9367 
9368    Level: advanced
9369 
9370    References:
9371 
9372 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9373 @*/
9374 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) {
9375   PetscFunctionBegin;
9376   PetscValidType(F, 1);
9377   PetscValidType(rhs, 2);
9378   PetscValidType(sol, 3);
9379   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9380   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9381   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9382   PetscCheckSameComm(F, 1, rhs, 2);
9383   PetscCheckSameComm(F, 1, sol, 3);
9384   PetscCall(MatFactorFactorizeSchurComplement(F));
9385   switch (F->schur_status) {
9386   case MAT_FACTOR_SCHUR_FACTORED: PetscCall(MatSolve(F->schur, rhs, sol)); break;
9387   case MAT_FACTOR_SCHUR_INVERTED: PetscCall(MatMult(F->schur, rhs, sol)); break;
9388   default: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9389   }
9390   PetscFunctionReturn(0);
9391 }
9392 
9393 /*@
9394   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9395 
9396    Logically Collective on Mat
9397 
9398    Input Parameters:
9399 .  F - the factored matrix obtained by calling MatGetFactor()
9400 
9401    Notes:
9402     Must be called after MatFactorSetSchurIS().
9403 
9404    Call MatFactorGetSchurComplement() or  MatFactorCreateSchurComplement() AFTER this call to actually compute the inverse and get access to it.
9405 
9406    Level: advanced
9407 
9408    References:
9409 
9410 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9411 @*/
9412 PetscErrorCode MatFactorInvertSchurComplement(Mat F) {
9413   PetscFunctionBegin;
9414   PetscValidType(F, 1);
9415   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9416   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9417   PetscCall(MatFactorFactorizeSchurComplement(F));
9418   PetscCall(MatFactorInvertSchurComplement_Private(F));
9419   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9420   PetscFunctionReturn(0);
9421 }
9422 
9423 /*@
9424   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9425 
9426    Logically Collective on Mat
9427 
9428    Input Parameters:
9429 .  F - the factored matrix obtained by calling MatGetFactor()
9430 
9431    Notes:
9432     Must be called after MatFactorSetSchurIS().
9433 
9434    Level: advanced
9435 
9436    References:
9437 
9438 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9439 @*/
9440 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) {
9441   PetscFunctionBegin;
9442   PetscValidType(F, 1);
9443   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9444   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9445   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9446   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9447   PetscFunctionReturn(0);
9448 }
9449 
9450 /*@
9451    MatPtAP - Creates the matrix product C = P^T * A * P
9452 
9453    Neighbor-wise Collective on Mat
9454 
9455    Input Parameters:
9456 +  A - the matrix
9457 .  P - the projection matrix
9458 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9459 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use PETSC_DEFAULT if you do not have a good estimate
9460           if the result is a dense matrix this is irrelevant
9461 
9462    Output Parameters:
9463 .  C - the product matrix
9464 
9465    Notes:
9466    C will be created and must be destroyed by the user with MatDestroy().
9467 
9468    For matrix types without special implementation the function fallbacks to MatMatMult() followed by MatTransposeMatMult().
9469 
9470    Level: intermediate
9471 
9472 .seealso: `MatMatMult()`, `MatRARt()`
9473 @*/
9474 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) {
9475   PetscFunctionBegin;
9476   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9477   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9478 
9479   if (scall == MAT_INITIAL_MATRIX) {
9480     PetscCall(MatProductCreate(A, P, NULL, C));
9481     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9482     PetscCall(MatProductSetAlgorithm(*C, "default"));
9483     PetscCall(MatProductSetFill(*C, fill));
9484 
9485     (*C)->product->api_user = PETSC_TRUE;
9486     PetscCall(MatProductSetFromOptions(*C));
9487     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);
9488     PetscCall(MatProductSymbolic(*C));
9489   } else { /* scall == MAT_REUSE_MATRIX */
9490     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9491   }
9492 
9493   PetscCall(MatProductNumeric(*C));
9494   (*C)->symmetric = A->symmetric;
9495   (*C)->spd       = A->spd;
9496   PetscFunctionReturn(0);
9497 }
9498 
9499 /*@
9500    MatRARt - Creates the matrix product C = R * A * R^T
9501 
9502    Neighbor-wise Collective on Mat
9503 
9504    Input Parameters:
9505 +  A - the matrix
9506 .  R - the projection matrix
9507 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9508 -  fill - expected fill as ratio of nnz(C)/nnz(A), use PETSC_DEFAULT if you do not have a good estimate
9509           if the result is a dense matrix this is irrelevant
9510 
9511    Output Parameters:
9512 .  C - the product matrix
9513 
9514    Notes:
9515    C will be created and must be destroyed by the user with MatDestroy().
9516 
9517    This routine is currently only implemented for pairs of AIJ matrices and classes
9518    which inherit from AIJ. Due to PETSc sparse matrix block row distribution among processes,
9519    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9520    We recommend using MatPtAP().
9521 
9522    Level: intermediate
9523 
9524 .seealso: `MatMatMult()`, `MatPtAP()`
9525 @*/
9526 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) {
9527   PetscFunctionBegin;
9528   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9529   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9530 
9531   if (scall == MAT_INITIAL_MATRIX) {
9532     PetscCall(MatProductCreate(A, R, NULL, C));
9533     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9534     PetscCall(MatProductSetAlgorithm(*C, "default"));
9535     PetscCall(MatProductSetFill(*C, fill));
9536 
9537     (*C)->product->api_user = PETSC_TRUE;
9538     PetscCall(MatProductSetFromOptions(*C));
9539     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);
9540     PetscCall(MatProductSymbolic(*C));
9541   } else { /* scall == MAT_REUSE_MATRIX */
9542     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9543   }
9544 
9545   PetscCall(MatProductNumeric(*C));
9546   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9547   PetscFunctionReturn(0);
9548 }
9549 
9550 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) {
9551   PetscFunctionBegin;
9552   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9553 
9554   if (scall == MAT_INITIAL_MATRIX) {
9555     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9556     PetscCall(MatProductCreate(A, B, NULL, C));
9557     PetscCall(MatProductSetType(*C, ptype));
9558     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9559     PetscCall(MatProductSetFill(*C, fill));
9560 
9561     (*C)->product->api_user = PETSC_TRUE;
9562     PetscCall(MatProductSetFromOptions(*C));
9563     PetscCall(MatProductSymbolic(*C));
9564   } else { /* scall == MAT_REUSE_MATRIX */
9565     Mat_Product *product = (*C)->product;
9566     PetscBool    isdense;
9567 
9568     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9569     if (isdense && product && product->type != ptype) {
9570       PetscCall(MatProductClear(*C));
9571       product = NULL;
9572     }
9573     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9574     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9575       if (isdense) {
9576         PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9577         product           = (*C)->product;
9578         product->fill     = fill;
9579         product->api_user = PETSC_TRUE;
9580         product->clear    = PETSC_TRUE;
9581 
9582         PetscCall(MatProductSetType(*C, ptype));
9583         PetscCall(MatProductSetFromOptions(*C));
9584         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);
9585         PetscCall(MatProductSymbolic(*C));
9586       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9587     } else { /* user may change input matrices A or B when REUSE */
9588       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9589     }
9590   }
9591   PetscCall(MatProductNumeric(*C));
9592   PetscFunctionReturn(0);
9593 }
9594 
9595 /*@
9596    MatMatMult - Performs Matrix-Matrix Multiplication C=A*B.
9597 
9598    Neighbor-wise Collective on Mat
9599 
9600    Input Parameters:
9601 +  A - the left matrix
9602 .  B - the right matrix
9603 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9604 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if you do not have a good estimate
9605           if the result is a dense matrix this is irrelevant
9606 
9607    Output Parameters:
9608 .  C - the product matrix
9609 
9610    Notes:
9611    Unless scall is MAT_REUSE_MATRIX C will be created.
9612 
9613    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
9614    call to this function with MAT_INITIAL_MATRIX.
9615 
9616    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9617 
9618    If you have many matrices with the same non-zero structure to multiply, you should use MatProductCreate()/MatProductSymbolic()/MatProductReplaceMats(), and call MatProductNumeric() repeatedly.
9619 
9620    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, rather than first having MatMatMult() create it for you. You can NEVER do this if the matrix C is sparse.
9621 
9622    Example of Usage:
9623 .vb
9624      MatProductCreate(A,B,NULL,&C);
9625      MatProductSetType(C,MATPRODUCT_AB);
9626      MatProductSymbolic(C);
9627      MatProductNumeric(C); // compute C=A * B
9628      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9629      MatProductNumeric(C);
9630      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9631      MatProductNumeric(C);
9632 .ve
9633 
9634    Level: intermediate
9635 
9636 .seealso: `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9637 @*/
9638 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9639   PetscFunctionBegin;
9640   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
9641   PetscFunctionReturn(0);
9642 }
9643 
9644 /*@
9645    MatMatTransposeMult - Performs Matrix-Matrix Multiplication C=A*B^T.
9646 
9647    Neighbor-wise Collective on Mat
9648 
9649    Input Parameters:
9650 +  A - the left matrix
9651 .  B - the right matrix
9652 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9653 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9654 
9655    Output Parameters:
9656 .  C - the product matrix
9657 
9658    Notes:
9659    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9660 
9661    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9662 
9663   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9664    actually needed.
9665 
9666    This routine is currently only implemented for pairs of SeqAIJ matrices, for the SeqDense class,
9667    and for pairs of MPIDense matrices.
9668 
9669    Options Database Keys:
9670 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for MPIDense matrices: the
9671               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9672               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9673 
9674    Level: intermediate
9675 
9676 .seealso: `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`
9677 @*/
9678 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9679   PetscFunctionBegin;
9680   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
9681   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9682   PetscFunctionReturn(0);
9683 }
9684 
9685 /*@
9686    MatTransposeMatMult - Performs Matrix-Matrix Multiplication C=A^T*B.
9687 
9688    Neighbor-wise Collective on Mat
9689 
9690    Input Parameters:
9691 +  A - the left matrix
9692 .  B - the right matrix
9693 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9694 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use PETSC_DEFAULT if not known
9695 
9696    Output Parameters:
9697 .  C - the product matrix
9698 
9699    Notes:
9700    C will be created if MAT_INITIAL_MATRIX and must be destroyed by the user with MatDestroy().
9701 
9702    MAT_REUSE_MATRIX can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9703 
9704   To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9705    actually needed.
9706 
9707    This routine is currently implemented for pairs of AIJ matrices and pairs of SeqDense matrices and classes
9708    which inherit from SeqAIJ.  C will be of the same type as the input matrices.
9709 
9710    Level: intermediate
9711 
9712 .seealso: `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9713 @*/
9714 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9715   PetscFunctionBegin;
9716   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
9717   PetscFunctionReturn(0);
9718 }
9719 
9720 /*@
9721    MatMatMatMult - Performs Matrix-Matrix-Matrix Multiplication D=A*B*C.
9722 
9723    Neighbor-wise Collective on Mat
9724 
9725    Input Parameters:
9726 +  A - the left matrix
9727 .  B - the middle matrix
9728 .  C - the right matrix
9729 .  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9730 -  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
9731           if the result is a dense matrix this is irrelevant
9732 
9733    Output Parameters:
9734 .  D - the product matrix
9735 
9736    Notes:
9737    Unless scall is MAT_REUSE_MATRIX D will be created.
9738 
9739    MAT_REUSE_MATRIX can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9740 
9741    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9742    actually needed.
9743 
9744    If you have many matrices with the same non-zero structure to multiply, you
9745    should use MAT_REUSE_MATRIX in all calls but the first
9746 
9747    Level: intermediate
9748 
9749 .seealso: `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9750 @*/
9751 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) {
9752   PetscFunctionBegin;
9753   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
9754   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9755 
9756   if (scall == MAT_INITIAL_MATRIX) {
9757     PetscCall(MatProductCreate(A, B, C, D));
9758     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
9759     PetscCall(MatProductSetAlgorithm(*D, "default"));
9760     PetscCall(MatProductSetFill(*D, fill));
9761 
9762     (*D)->product->api_user = PETSC_TRUE;
9763     PetscCall(MatProductSetFromOptions(*D));
9764     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,
9765                ((PetscObject)C)->type_name);
9766     PetscCall(MatProductSymbolic(*D));
9767   } else { /* user may change input matrices when REUSE */
9768     PetscCall(MatProductReplaceMats(A, B, C, *D));
9769   }
9770   PetscCall(MatProductNumeric(*D));
9771   PetscFunctionReturn(0);
9772 }
9773 
9774 /*@
9775    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9776 
9777    Collective on Mat
9778 
9779    Input Parameters:
9780 +  mat - the matrix
9781 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9782 .  subcomm - MPI communicator split from the communicator where mat resides in (or MPI_COMM_NULL if nsubcomm is used)
9783 -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9784 
9785    Output Parameter:
9786 .  matredundant - redundant matrix
9787 
9788    Notes:
9789    MAT_REUSE_MATRIX can only be used when the nonzero structure of the
9790    original matrix has not changed from that last call to MatCreateRedundantMatrix().
9791 
9792    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9793    calling it.
9794 
9795    Level: advanced
9796 
9797 .seealso: `MatDestroy()`
9798 @*/
9799 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) {
9800   MPI_Comm       comm;
9801   PetscMPIInt    size;
9802   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9803   Mat_Redundant *redund     = NULL;
9804   PetscSubcomm   psubcomm   = NULL;
9805   MPI_Comm       subcomm_in = subcomm;
9806   Mat           *matseq;
9807   IS             isrow, iscol;
9808   PetscBool      newsubcomm = PETSC_FALSE;
9809 
9810   PetscFunctionBegin;
9811   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9812   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9813     PetscValidPointer(*matredundant, 5);
9814     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
9815   }
9816 
9817   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9818   if (size == 1 || nsubcomm == 1) {
9819     if (reuse == MAT_INITIAL_MATRIX) {
9820       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
9821     } else {
9822       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");
9823       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
9824     }
9825     PetscFunctionReturn(0);
9826   }
9827 
9828   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9829   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9830   MatCheckPreallocated(mat, 1);
9831 
9832   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
9833   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9834     /* create psubcomm, then get subcomm */
9835     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
9836     PetscCallMPI(MPI_Comm_size(comm, &size));
9837     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
9838 
9839     PetscCall(PetscSubcommCreate(comm, &psubcomm));
9840     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
9841     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
9842     PetscCall(PetscSubcommSetFromOptions(psubcomm));
9843     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
9844     newsubcomm = PETSC_TRUE;
9845     PetscCall(PetscSubcommDestroy(&psubcomm));
9846   }
9847 
9848   /* get isrow, iscol and a local sequential matrix matseq[0] */
9849   if (reuse == MAT_INITIAL_MATRIX) {
9850     mloc_sub = PETSC_DECIDE;
9851     nloc_sub = PETSC_DECIDE;
9852     if (bs < 1) {
9853       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
9854       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
9855     } else {
9856       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
9857       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
9858     }
9859     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
9860     rstart = rend - mloc_sub;
9861     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
9862     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
9863   } else { /* reuse == MAT_REUSE_MATRIX */
9864     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");
9865     /* retrieve subcomm */
9866     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
9867     redund = (*matredundant)->redundant;
9868     isrow  = redund->isrow;
9869     iscol  = redund->iscol;
9870     matseq = redund->matseq;
9871   }
9872   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
9873 
9874   /* get matredundant over subcomm */
9875   if (reuse == MAT_INITIAL_MATRIX) {
9876     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
9877 
9878     /* create a supporting struct and attach it to C for reuse */
9879     PetscCall(PetscNewLog(*matredundant, &redund));
9880     (*matredundant)->redundant = redund;
9881     redund->isrow              = isrow;
9882     redund->iscol              = iscol;
9883     redund->matseq             = matseq;
9884     if (newsubcomm) {
9885       redund->subcomm = subcomm;
9886     } else {
9887       redund->subcomm = MPI_COMM_NULL;
9888     }
9889   } else {
9890     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
9891   }
9892 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9893   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9894     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
9895     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
9896   }
9897 #endif
9898   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
9899   PetscFunctionReturn(0);
9900 }
9901 
9902 /*@C
9903    MatGetMultiProcBlock - Create multiple [bjacobi] 'parallel submatrices' from
9904    a given 'mat' object. Each submatrix can span multiple procs.
9905 
9906    Collective on Mat
9907 
9908    Input Parameters:
9909 +  mat - the matrix
9910 .  subcomm - the subcommunicator obtained by com_split(comm)
9911 -  scall - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
9912 
9913    Output Parameter:
9914 .  subMat - 'parallel submatrices each spans a given subcomm
9915 
9916   Notes:
9917   The submatrix partition across processors is dictated by 'subComm' a
9918   communicator obtained by MPI_comm_split(). The subComm
9919   is not restriced to be grouped with consecutive original ranks.
9920 
9921   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
9922   map directly to the layout of the original matrix [wrt the local
9923   row,col partitioning]. So the original 'DiagonalMat' naturally maps
9924   into the 'DiagonalMat' of the subMat, hence it is used directly from
9925   the subMat. However the offDiagMat looses some columns - and this is
9926   reconstructed with MatSetValues()
9927 
9928   Level: advanced
9929 
9930 .seealso: `MatCreateSubMatrices()`
9931 @*/
9932 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) {
9933   PetscMPIInt commsize, subCommSize;
9934 
9935   PetscFunctionBegin;
9936   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
9937   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
9938   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
9939 
9940   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");
9941   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
9942   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
9943   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
9944   PetscFunctionReturn(0);
9945 }
9946 
9947 /*@
9948    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
9949 
9950    Not Collective
9951 
9952    Input Parameters:
9953 +  mat - matrix to extract local submatrix from
9954 .  isrow - local row indices for submatrix
9955 -  iscol - local column indices for submatrix
9956 
9957    Output Parameter:
9958 .  submat - the submatrix
9959 
9960    Level: intermediate
9961 
9962    Notes:
9963    The submat should be returned with MatRestoreLocalSubMatrix().
9964 
9965    Depending on the format of mat, the returned submat may not implement MatMult().  Its communicator may be
9966    the same as mat, it may be PETSC_COMM_SELF, or some other subcomm of mat's.
9967 
9968    The submat always implements MatSetValuesLocal().  If isrow and iscol have the same block size, then
9969    MatSetValuesBlockedLocal() will also be implemented.
9970 
9971    The mat must have had a ISLocalToGlobalMapping provided to it with MatSetLocalToGlobalMapping(). Note that
9972    matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
9973 
9974 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
9975 @*/
9976 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) {
9977   PetscFunctionBegin;
9978   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9979   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
9980   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
9981   PetscCheckSameComm(isrow, 2, iscol, 3);
9982   PetscValidPointer(submat, 4);
9983   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
9984 
9985   if (mat->ops->getlocalsubmatrix) {
9986     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
9987   } else {
9988     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
9989   }
9990   PetscFunctionReturn(0);
9991 }
9992 
9993 /*@
9994    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering
9995 
9996    Not Collective
9997 
9998    Input Parameters:
9999 +  mat - matrix to extract local submatrix from
10000 .  isrow - local row indices for submatrix
10001 .  iscol - local column indices for submatrix
10002 -  submat - the submatrix
10003 
10004    Level: intermediate
10005 
10006 .seealso: `MatGetLocalSubMatrix()`
10007 @*/
10008 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) {
10009   PetscFunctionBegin;
10010   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10011   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10012   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10013   PetscCheckSameComm(isrow, 2, iscol, 3);
10014   PetscValidPointer(submat, 4);
10015   if (*submat) { PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4); }
10016 
10017   if (mat->ops->restorelocalsubmatrix) {
10018     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10019   } else {
10020     PetscCall(MatDestroy(submat));
10021   }
10022   *submat = NULL;
10023   PetscFunctionReturn(0);
10024 }
10025 
10026 /* --------------------------------------------------------*/
10027 /*@
10028    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10029 
10030    Collective on Mat
10031 
10032    Input Parameter:
10033 .  mat - the matrix
10034 
10035    Output Parameter:
10036 .  is - if any rows have zero diagonals this contains the list of them
10037 
10038    Level: developer
10039 
10040 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10041 @*/
10042 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) {
10043   PetscFunctionBegin;
10044   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10045   PetscValidType(mat, 1);
10046   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10047   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10048 
10049   if (!mat->ops->findzerodiagonals) {
10050     Vec                diag;
10051     const PetscScalar *a;
10052     PetscInt          *rows;
10053     PetscInt           rStart, rEnd, r, nrow = 0;
10054 
10055     PetscCall(MatCreateVecs(mat, &diag, NULL));
10056     PetscCall(MatGetDiagonal(mat, diag));
10057     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10058     PetscCall(VecGetArrayRead(diag, &a));
10059     for (r = 0; r < rEnd - rStart; ++r)
10060       if (a[r] == 0.0) ++nrow;
10061     PetscCall(PetscMalloc1(nrow, &rows));
10062     nrow = 0;
10063     for (r = 0; r < rEnd - rStart; ++r)
10064       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10065     PetscCall(VecRestoreArrayRead(diag, &a));
10066     PetscCall(VecDestroy(&diag));
10067     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10068   } else {
10069     PetscUseTypeMethod(mat, findzerodiagonals, is);
10070   }
10071   PetscFunctionReturn(0);
10072 }
10073 
10074 /*@
10075    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10076 
10077    Collective on Mat
10078 
10079    Input Parameter:
10080 .  mat - the matrix
10081 
10082    Output Parameter:
10083 .  is - contains the list of rows with off block diagonal entries
10084 
10085    Level: developer
10086 
10087 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10088 @*/
10089 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) {
10090   PetscFunctionBegin;
10091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10092   PetscValidType(mat, 1);
10093   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10094   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10095 
10096   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10097   PetscFunctionReturn(0);
10098 }
10099 
10100 /*@C
10101   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10102 
10103   Collective on Mat
10104 
10105   Input Parameters:
10106 . mat - the matrix
10107 
10108   Output Parameters:
10109 . values - the block inverses in column major order (FORTRAN-like)
10110 
10111    Note:
10112      The size of the blocks is determined by the block size of the matrix.
10113 
10114    Fortran Note:
10115      This routine is not available from Fortran.
10116 
10117   Level: advanced
10118 
10119 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10120 @*/
10121 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) {
10122   PetscFunctionBegin;
10123   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10124   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10125   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10126   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10127   PetscFunctionReturn(0);
10128 }
10129 
10130 /*@C
10131   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10132 
10133   Collective on Mat
10134 
10135   Input Parameters:
10136 + mat - the matrix
10137 . nblocks - the number of blocks on the process, set with MatSetVariableBlockSizes()
10138 - bsizes - the size of each block on the process, set with MatSetVariableBlockSizes()
10139 
10140   Output Parameters:
10141 . values - the block inverses in column major order (FORTRAN-like)
10142 
10143    Note:
10144    This routine is not available from Fortran.
10145 
10146   Level: advanced
10147 
10148 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10149 @*/
10150 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) {
10151   PetscFunctionBegin;
10152   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10153   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10154   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10155   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10156   PetscFunctionReturn(0);
10157 }
10158 
10159 /*@
10160   MatInvertBlockDiagonalMat - set matrix C to be the inverted block diagonal of matrix A
10161 
10162   Collective on Mat
10163 
10164   Input Parameters:
10165 . A - the matrix
10166 
10167   Output Parameters:
10168 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10169 
10170   Notes: the blocksize of the matrix is used to determine the blocks on the diagonal of C
10171 
10172   Level: advanced
10173 
10174 .seealso: `MatInvertBlockDiagonal()`
10175 @*/
10176 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) {
10177   const PetscScalar *vals;
10178   PetscInt          *dnnz;
10179   PetscInt           m, rstart, rend, bs, i, j;
10180 
10181   PetscFunctionBegin;
10182   PetscCall(MatInvertBlockDiagonal(A, &vals));
10183   PetscCall(MatGetBlockSize(A, &bs));
10184   PetscCall(MatGetLocalSize(A, &m, NULL));
10185   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10186   PetscCall(PetscMalloc1(m / bs, &dnnz));
10187   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10188   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10189   PetscCall(PetscFree(dnnz));
10190   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10191   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10192   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10193   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10194   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10195   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10196   PetscFunctionReturn(0);
10197 }
10198 
10199 /*@C
10200     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10201     via MatTransposeColoringCreate().
10202 
10203     Collective on MatTransposeColoring
10204 
10205     Input Parameter:
10206 .   c - coloring context
10207 
10208     Level: intermediate
10209 
10210 .seealso: `MatTransposeColoringCreate()`
10211 @*/
10212 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) {
10213   MatTransposeColoring matcolor = *c;
10214 
10215   PetscFunctionBegin;
10216   if (!matcolor) PetscFunctionReturn(0);
10217   if (--((PetscObject)matcolor)->refct > 0) {
10218     matcolor = NULL;
10219     PetscFunctionReturn(0);
10220   }
10221 
10222   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10223   PetscCall(PetscFree(matcolor->rows));
10224   PetscCall(PetscFree(matcolor->den2sp));
10225   PetscCall(PetscFree(matcolor->colorforcol));
10226   PetscCall(PetscFree(matcolor->columns));
10227   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10228   PetscCall(PetscHeaderDestroy(c));
10229   PetscFunctionReturn(0);
10230 }
10231 
10232 /*@C
10233     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10234     a MatTransposeColoring context has been created, computes a dense B^T by Apply
10235     MatTransposeColoring to sparse B.
10236 
10237     Collective on MatTransposeColoring
10238 
10239     Input Parameters:
10240 +   B - sparse matrix B
10241 .   Btdense - symbolic dense matrix B^T
10242 -   coloring - coloring context created with MatTransposeColoringCreate()
10243 
10244     Output Parameter:
10245 .   Btdense - dense matrix B^T
10246 
10247     Level: advanced
10248 
10249      Notes:
10250     These are used internally for some implementations of MatRARt()
10251 
10252 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10253 
10254 @*/
10255 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) {
10256   PetscFunctionBegin;
10257   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10258   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10259   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10260 
10261   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10262   PetscFunctionReturn(0);
10263 }
10264 
10265 /*@C
10266     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10267     a MatTransposeColoring context has been created and a dense matrix Cden=A*Btdense
10268     in which Btdens is obtained from MatTransColoringApplySpToDen(), recover sparse matrix
10269     Csp from Cden.
10270 
10271     Collective on MatTransposeColoring
10272 
10273     Input Parameters:
10274 +   coloring - coloring context created with MatTransposeColoringCreate()
10275 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10276 
10277     Output Parameter:
10278 .   Csp - sparse matrix
10279 
10280     Level: advanced
10281 
10282      Notes:
10283     These are used internally for some implementations of MatRARt()
10284 
10285 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10286 
10287 @*/
10288 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) {
10289   PetscFunctionBegin;
10290   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10291   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10292   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10293 
10294   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10295   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10296   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10297   PetscFunctionReturn(0);
10298 }
10299 
10300 /*@C
10301    MatTransposeColoringCreate - Creates a matrix coloring context for matrix product C=A*B^T.
10302 
10303    Collective on Mat
10304 
10305    Input Parameters:
10306 +  mat - the matrix product C
10307 -  iscoloring - the coloring of the matrix; usually obtained with MatColoringCreate() or DMCreateColoring()
10308 
10309     Output Parameter:
10310 .   color - the new coloring context
10311 
10312     Level: intermediate
10313 
10314 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10315           `MatTransColoringApplyDenToSp()`
10316 @*/
10317 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) {
10318   MatTransposeColoring c;
10319   MPI_Comm             comm;
10320 
10321   PetscFunctionBegin;
10322   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10323   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10324   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10325 
10326   c->ctype = iscoloring->ctype;
10327   if (mat->ops->transposecoloringcreate) {
10328     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10329   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10330 
10331   *color = c;
10332   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10333   PetscFunctionReturn(0);
10334 }
10335 
10336 /*@
10337       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10338         matrix has had no new nonzero locations added to the matrix since the previous call then the value will be the
10339         same, otherwise it will be larger
10340 
10341      Not Collective
10342 
10343   Input Parameter:
10344 .    A  - the matrix
10345 
10346   Output Parameter:
10347 .    state - the current state
10348 
10349   Notes:
10350     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10351          different matrices
10352 
10353   Level: intermediate
10354 
10355 .seealso: `PetscObjectStateGet()`
10356 @*/
10357 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) {
10358   PetscFunctionBegin;
10359   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10360   *state = mat->nonzerostate;
10361   PetscFunctionReturn(0);
10362 }
10363 
10364 /*@
10365       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10366                  matrices from each processor
10367 
10368     Collective
10369 
10370    Input Parameters:
10371 +    comm - the communicators the parallel matrix will live on
10372 .    seqmat - the input sequential matrices
10373 .    n - number of local columns (or PETSC_DECIDE)
10374 -    reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10375 
10376    Output Parameter:
10377 .    mpimat - the parallel matrix generated
10378 
10379     Level: advanced
10380 
10381    Notes:
10382     The number of columns of the matrix in EACH processor MUST be the same.
10383 
10384 @*/
10385 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) {
10386   PetscMPIInt size;
10387 
10388   PetscFunctionBegin;
10389   PetscCallMPI(MPI_Comm_size(comm, &size));
10390   if (size == 1) {
10391     if (reuse == MAT_INITIAL_MATRIX) {
10392       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10393     } else {
10394       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10395     }
10396     PetscFunctionReturn(0);
10397   }
10398 
10399   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");
10400 
10401   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10402   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10403   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10404   PetscFunctionReturn(0);
10405 }
10406 
10407 /*@
10408      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent
10409                  ranks' ownership ranges.
10410 
10411     Collective on A
10412 
10413    Input Parameters:
10414 +    A   - the matrix to create subdomains from
10415 -    N   - requested number of subdomains
10416 
10417    Output Parameters:
10418 +    n   - number of subdomains resulting on this rank
10419 -    iss - IS list with indices of subdomains on this rank
10420 
10421     Level: advanced
10422 
10423     Notes:
10424     number of subdomains must be smaller than the communicator size
10425 @*/
10426 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) {
10427   MPI_Comm    comm, subcomm;
10428   PetscMPIInt size, rank, color;
10429   PetscInt    rstart, rend, k;
10430 
10431   PetscFunctionBegin;
10432   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10433   PetscCallMPI(MPI_Comm_size(comm, &size));
10434   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10435   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);
10436   *n    = 1;
10437   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10438   color = rank / k;
10439   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10440   PetscCall(PetscMalloc1(1, iss));
10441   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10442   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10443   PetscCallMPI(MPI_Comm_free(&subcomm));
10444   PetscFunctionReturn(0);
10445 }
10446 
10447 /*@
10448    MatGalerkin - Constructs the coarse grid problem via Galerkin projection.
10449 
10450    If the interpolation and restriction operators are the same, uses MatPtAP.
10451    If they are not the same, use MatMatMatMult.
10452 
10453    Once the coarse grid problem is constructed, correct for interpolation operators
10454    that are not of full rank, which can legitimately happen in the case of non-nested
10455    geometric multigrid.
10456 
10457    Input Parameters:
10458 +  restrct - restriction operator
10459 .  dA - fine grid matrix
10460 .  interpolate - interpolation operator
10461 .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
10462 -  fill - expected fill, use PETSC_DEFAULT if you do not have a good estimate
10463 
10464    Output Parameters:
10465 .  A - the Galerkin coarse matrix
10466 
10467    Options Database Key:
10468 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10469 
10470    Level: developer
10471 
10472 .seealso: `MatPtAP()`, `MatMatMatMult()`
10473 @*/
10474 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) {
10475   IS  zerorows;
10476   Vec diag;
10477 
10478   PetscFunctionBegin;
10479   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10480   /* Construct the coarse grid matrix */
10481   if (interpolate == restrct) {
10482     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10483   } else {
10484     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10485   }
10486 
10487   /* If the interpolation matrix is not of full rank, A will have zero rows.
10488      This can legitimately happen in the case of non-nested geometric multigrid.
10489      In that event, we set the rows of the matrix to the rows of the identity,
10490      ignoring the equations (as the RHS will also be zero). */
10491 
10492   PetscCall(MatFindZeroRows(*A, &zerorows));
10493 
10494   if (zerorows != NULL) { /* if there are any zero rows */
10495     PetscCall(MatCreateVecs(*A, &diag, NULL));
10496     PetscCall(MatGetDiagonal(*A, diag));
10497     PetscCall(VecISSet(diag, zerorows, 1.0));
10498     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10499     PetscCall(VecDestroy(&diag));
10500     PetscCall(ISDestroy(&zerorows));
10501   }
10502   PetscFunctionReturn(0);
10503 }
10504 
10505 /*@C
10506     MatSetOperation - Allows user to set a matrix operation for any matrix type
10507 
10508    Logically Collective on Mat
10509 
10510     Input Parameters:
10511 +   mat - the matrix
10512 .   op - the name of the operation
10513 -   f - the function that provides the operation
10514 
10515    Level: developer
10516 
10517     Usage:
10518 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10519 $      PetscCall(MatCreateXXX(comm,...&A);
10520 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10521 
10522     Notes:
10523     See the file include/petscmat.h for a complete list of matrix
10524     operations, which all have the form MATOP_<OPERATION>, where
10525     <OPERATION> is the name (in all capital letters) of the
10526     user interface routine (e.g., MatMult() -> MATOP_MULT).
10527 
10528     All user-provided functions (except for MATOP_DESTROY) should have the same calling
10529     sequence as the usual matrix interface routines, since they
10530     are intended to be accessed via the usual matrix interface
10531     routines, e.g.,
10532 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10533 
10534     In particular each function MUST return an error code of 0 on success and
10535     nonzero on failure.
10536 
10537     This routine is distinct from MatShellSetOperation() in that it can be called on any matrix type.
10538 
10539 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10540 @*/
10541 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) {
10542   PetscFunctionBegin;
10543   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10544   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) { mat->ops->viewnative = mat->ops->view; }
10545   (((void (**)(void))mat->ops)[op]) = f;
10546   PetscFunctionReturn(0);
10547 }
10548 
10549 /*@C
10550     MatGetOperation - Gets a matrix operation for any matrix type.
10551 
10552     Not Collective
10553 
10554     Input Parameters:
10555 +   mat - the matrix
10556 -   op - the name of the operation
10557 
10558     Output Parameter:
10559 .   f - the function that provides the operation
10560 
10561     Level: developer
10562 
10563     Usage:
10564 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10565 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10566 
10567     Notes:
10568     See the file include/petscmat.h for a complete list of matrix
10569     operations, which all have the form MATOP_<OPERATION>, where
10570     <OPERATION> is the name (in all capital letters) of the
10571     user interface routine (e.g., MatMult() -> MATOP_MULT).
10572 
10573     This routine is distinct from MatShellGetOperation() in that it can be called on any matrix type.
10574 
10575 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10576 @*/
10577 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) {
10578   PetscFunctionBegin;
10579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10580   *f = (((void (**)(void))mat->ops)[op]);
10581   PetscFunctionReturn(0);
10582 }
10583 
10584 /*@
10585     MatHasOperation - Determines whether the given matrix supports the particular
10586     operation.
10587 
10588    Not Collective
10589 
10590    Input Parameters:
10591 +  mat - the matrix
10592 -  op - the operation, for example, MATOP_GET_DIAGONAL
10593 
10594    Output Parameter:
10595 .  has - either PETSC_TRUE or PETSC_FALSE
10596 
10597    Level: advanced
10598 
10599    Notes:
10600    See the file include/petscmat.h for a complete list of matrix
10601    operations, which all have the form MATOP_<OPERATION>, where
10602    <OPERATION> is the name (in all capital letters) of the
10603    user-level routine.  E.g., MatNorm() -> MATOP_NORM.
10604 
10605 .seealso: `MatCreateShell()`
10606 @*/
10607 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) {
10608   PetscFunctionBegin;
10609   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10610   PetscValidBoolPointer(has, 3);
10611   if (mat->ops->hasoperation) {
10612     PetscUseTypeMethod(mat, hasoperation, op, has);
10613   } else {
10614     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10615     else {
10616       *has = PETSC_FALSE;
10617       if (op == MATOP_CREATE_SUBMATRIX) {
10618         PetscMPIInt size;
10619 
10620         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10621         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
10622       }
10623     }
10624   }
10625   PetscFunctionReturn(0);
10626 }
10627 
10628 /*@
10629     MatHasCongruentLayouts - Determines whether the rows and columns layouts
10630     of the matrix are congruent
10631 
10632    Collective on mat
10633 
10634    Input Parameters:
10635 .  mat - the matrix
10636 
10637    Output Parameter:
10638 .  cong - either PETSC_TRUE or PETSC_FALSE
10639 
10640    Level: beginner
10641 
10642    Notes:
10643 
10644 .seealso: `MatCreate()`, `MatSetSizes()`
10645 @*/
10646 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) {
10647   PetscFunctionBegin;
10648   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10649   PetscValidType(mat, 1);
10650   PetscValidBoolPointer(cong, 2);
10651   if (!mat->rmap || !mat->cmap) {
10652     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10653     PetscFunctionReturn(0);
10654   }
10655   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10656     PetscCall(PetscLayoutSetUp(mat->rmap));
10657     PetscCall(PetscLayoutSetUp(mat->cmap));
10658     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
10659     if (*cong) mat->congruentlayouts = 1;
10660     else mat->congruentlayouts = 0;
10661   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10662   PetscFunctionReturn(0);
10663 }
10664 
10665 PetscErrorCode MatSetInf(Mat A) {
10666   PetscFunctionBegin;
10667   PetscUseTypeMethod(A, setinf);
10668   PetscFunctionReturn(0);
10669 }
10670 
10671 /*C
10672    MatCreateGraph - create a scalar matrix, for use in graph algorithms
10673 
10674    Collective on mat
10675 
10676    Input Parameters:
10677 +  A - the matrix
10678 -  sym - PETSC_TRUE indicates that the graph will be symmetrized
10679 .  scale - PETSC_TRUE indicates that the graph will be scaled with the diagonal
10680 
10681    Output Parameter:
10682 .  graph - the resulting graph
10683 
10684    Level: advanced
10685 
10686    Notes:
10687 
10688 .seealso: `MatCreate()`, `MatFilter()`
10689 */
10690 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, Mat *graph) {
10691   PetscFunctionBegin;
10692   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
10693   PetscValidType(A, 1);
10694   PetscValidPointer(graph, 3);
10695   PetscUseTypeMethod(A, creategraph, sym, scale, graph);
10696   PetscFunctionReturn(0);
10697 }
10698 
10699 /*C
10700    MatFilter - filters a Mat values with an absolut value equal to or below a give threshold
10701 
10702    Collective on mat
10703 
10704    Input Parameter:
10705 .  value - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries <= value
10706 
10707    Input/Output Parameter:
10708 .  A - the Mat to filter in place
10709 
10710    Level: developer
10711 
10712    Note:
10713    This is called before graph coarsers are called in GAMG
10714 
10715 .seealso: `MatCreate()`, `MatCreateGraph()`
10716 */
10717 PETSC_EXTERN PetscErrorCode MatFilter(Mat G, PetscReal value, Mat *F) {
10718   PetscFunctionBegin;
10719   PetscValidHeaderSpecific(G, MAT_CLASSID, 1);
10720   PetscValidType(G, 1);
10721   PetscValidPointer(F, 3);
10722   if (value >= 0.0) PetscCall((G->ops->filter)(G, value, F));
10723   PetscFunctionReturn(0);
10724 }
10725