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