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