xref: /petsc/src/mat/interface/matrix.c (revision 5520554388890bd89a1c1cf7870aedf4e71d512f)
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_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
3997          upper/lower triangular part of matrix to
3998          vector (with omega)
3999 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4000 
4001    Notes:
4002    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4003    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4004    on each processor.
4005 
4006    Application programmers will not generally use `MatSOR()` directly,
4007    but instead will employ the `KSP`/`PC` interface.
4008 
4009    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4010 
4011    Most users should employ the `KSP` interface for linear solvers
4012    instead of working directly with matrix algebra routines such as this.
4013    See, e.g., `KSPCreate()`.
4014 
4015    Vectors x and b CANNOT be the same
4016 
4017    Notes for Advanced Users:
4018    The flags are implemented as bitwise inclusive or operations.
4019    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4020    to specify a zero initial guess for SSOR.
4021 
4022    Developer Note:
4023    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4024 
4025    Level: developer
4026 
4027 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4028 @*/
4029 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) {
4030   PetscFunctionBegin;
4031   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4032   PetscValidType(mat, 1);
4033   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4034   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4035   PetscCheckSameComm(mat, 1, b, 2);
4036   PetscCheckSameComm(mat, 1, x, 8);
4037   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4038   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4039   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);
4040   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);
4041   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);
4042   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4043   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4044   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4045 
4046   MatCheckPreallocated(mat, 1);
4047   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4048   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4049   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4050   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4051   PetscFunctionReturn(0);
4052 }
4053 
4054 /*
4055       Default matrix copy routine.
4056 */
4057 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) {
4058   PetscInt           i, rstart = 0, rend = 0, nz;
4059   const PetscInt    *cwork;
4060   const PetscScalar *vwork;
4061 
4062   PetscFunctionBegin;
4063   if (B->assembled) PetscCall(MatZeroEntries(B));
4064   if (str == SAME_NONZERO_PATTERN) {
4065     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4066     for (i = rstart; i < rend; i++) {
4067       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4068       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4069       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4070     }
4071   } else {
4072     PetscCall(MatAYPX(B, 0.0, A, str));
4073   }
4074   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4075   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4076   PetscFunctionReturn(0);
4077 }
4078 
4079 /*@
4080    MatCopy - Copies a matrix to another matrix.
4081 
4082    Collective on A
4083 
4084    Input Parameters:
4085 +  A - the matrix
4086 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4087 
4088    Output Parameter:
4089 .  B - where the copy is put
4090 
4091    Notes:
4092    If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4093 
4094    `MatCopy()` copies the matrix entries of a matrix to another existing
4095    matrix (after first zeroing the second matrix).  A related routine is
4096    `MatConvert()`, which first creates a new matrix and then copies the data.
4097 
4098    Level: intermediate
4099 
4100 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4101 @*/
4102 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) {
4103   PetscInt i;
4104 
4105   PetscFunctionBegin;
4106   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4107   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4108   PetscValidType(A, 1);
4109   PetscValidType(B, 2);
4110   PetscCheckSameComm(A, 1, B, 2);
4111   MatCheckPreallocated(B, 2);
4112   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4113   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4114   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,
4115              A->cmap->N, B->cmap->N);
4116   MatCheckPreallocated(A, 1);
4117   if (A == B) PetscFunctionReturn(0);
4118 
4119   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4120   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4121   else PetscCall(MatCopy_Basic(A, B, str));
4122 
4123   B->stencil.dim = A->stencil.dim;
4124   B->stencil.noc = A->stencil.noc;
4125   for (i = 0; i <= A->stencil.dim; i++) {
4126     B->stencil.dims[i]   = A->stencil.dims[i];
4127     B->stencil.starts[i] = A->stencil.starts[i];
4128   }
4129 
4130   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4131   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4132   PetscFunctionReturn(0);
4133 }
4134 
4135 /*@C
4136    MatConvert - Converts a matrix to another matrix, either of the same
4137    or different type.
4138 
4139    Collective on mat
4140 
4141    Input Parameters:
4142 +  mat - the matrix
4143 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4144    same type as the original matrix.
4145 -  reuse - denotes if the destination matrix is to be created or reused.
4146    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
4147    `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).
4148 
4149    Output Parameter:
4150 .  M - pointer to place new matrix
4151 
4152    Notes:
4153    `MatConvert()` first creates a new matrix and then copies the data from
4154    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4155    entries of one matrix to another already existing matrix context.
4156 
4157    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4158    the MPI communicator of the generated matrix is always the same as the communicator
4159    of the input matrix.
4160 
4161    Level: intermediate
4162 
4163 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4164 @*/
4165 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) {
4166   PetscBool  sametype, issame, flg;
4167   PetscBool3 issymmetric, ishermitian;
4168   char       convname[256], mtype[256];
4169   Mat        B;
4170 
4171   PetscFunctionBegin;
4172   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4173   PetscValidType(mat, 1);
4174   PetscValidPointer(M, 4);
4175   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4176   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4177   MatCheckPreallocated(mat, 1);
4178 
4179   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4180   if (flg) newtype = mtype;
4181 
4182   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4183   PetscCall(PetscStrcmp(newtype, "same", &issame));
4184   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4185   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");
4186 
4187   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4188     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4189     PetscFunctionReturn(0);
4190   }
4191 
4192   /* Cache Mat options because some converters use MatHeaderReplace  */
4193   issymmetric = mat->symmetric;
4194   ishermitian = mat->hermitian;
4195 
4196   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4197     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4198     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4199   } else {
4200     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4201     const char *prefix[3]                                 = {"seq", "mpi", ""};
4202     PetscInt    i;
4203     /*
4204        Order of precedence:
4205        0) See if newtype is a superclass of the current matrix.
4206        1) See if a specialized converter is known to the current matrix.
4207        2) See if a specialized converter is known to the desired matrix class.
4208        3) See if a good general converter is registered for the desired class
4209           (as of 6/27/03 only MATMPIADJ falls into this category).
4210        4) See if a good general converter is known for the current matrix.
4211        5) Use a really basic converter.
4212     */
4213 
4214     /* 0) See if newtype is a superclass of the current matrix.
4215           i.e mat is mpiaij and newtype is aij */
4216     for (i = 0; i < 2; i++) {
4217       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4218       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4219       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4220       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4221       if (flg) {
4222         if (reuse == MAT_INPLACE_MATRIX) {
4223           PetscCall(PetscInfo(mat, "Early return\n"));
4224           PetscFunctionReturn(0);
4225         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4226           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4227           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4228           PetscFunctionReturn(0);
4229         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4230           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4231           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4232           PetscFunctionReturn(0);
4233         }
4234       }
4235     }
4236     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4237     for (i = 0; i < 3; i++) {
4238       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4239       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4240       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4241       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4242       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4243       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4244       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4245       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4246       if (conv) goto foundconv;
4247     }
4248 
4249     /* 2)  See if a specialized converter is known to the desired matrix class. */
4250     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4251     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4252     PetscCall(MatSetType(B, newtype));
4253     for (i = 0; i < 3; i++) {
4254       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4255       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4256       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4257       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4258       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4259       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4260       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4261       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4262       if (conv) {
4263         PetscCall(MatDestroy(&B));
4264         goto foundconv;
4265       }
4266     }
4267 
4268     /* 3) See if a good general converter is registered for the desired class */
4269     conv = B->ops->convertfrom;
4270     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4271     PetscCall(MatDestroy(&B));
4272     if (conv) goto foundconv;
4273 
4274     /* 4) See if a good general converter is known for the current matrix */
4275     if (mat->ops->convert) conv = mat->ops->convert;
4276     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4277     if (conv) goto foundconv;
4278 
4279     /* 5) Use a really basic converter. */
4280     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4281     conv = MatConvert_Basic;
4282 
4283   foundconv:
4284     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4285     PetscCall((*conv)(mat, newtype, reuse, M));
4286     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4287       /* the block sizes must be same if the mappings are copied over */
4288       (*M)->rmap->bs = mat->rmap->bs;
4289       (*M)->cmap->bs = mat->cmap->bs;
4290       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4291       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4292       (*M)->rmap->mapping = mat->rmap->mapping;
4293       (*M)->cmap->mapping = mat->cmap->mapping;
4294     }
4295     (*M)->stencil.dim = mat->stencil.dim;
4296     (*M)->stencil.noc = mat->stencil.noc;
4297     for (i = 0; i <= mat->stencil.dim; i++) {
4298       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4299       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4300     }
4301     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4302   }
4303   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4304 
4305   /* Copy Mat options */
4306   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4307   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4308   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4309   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4310   PetscFunctionReturn(0);
4311 }
4312 
4313 /*@C
4314    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4315 
4316    Not Collective
4317 
4318    Input Parameter:
4319 .  mat - the matrix, must be a factored matrix
4320 
4321    Output Parameter:
4322 .   type - the string name of the package (do not free this string)
4323 
4324    Note:
4325       In Fortran you pass in a empty string and the package name will be copied into it.
4326     (Make sure the string is long enough)
4327 
4328    Level: intermediate
4329 
4330 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4331 @*/
4332 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) {
4333   PetscErrorCode (*conv)(Mat, MatSolverType *);
4334 
4335   PetscFunctionBegin;
4336   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4337   PetscValidType(mat, 1);
4338   PetscValidPointer(type, 2);
4339   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4340   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4341   if (conv) PetscCall((*conv)(mat, type));
4342   else *type = MATSOLVERPETSC;
4343   PetscFunctionReturn(0);
4344 }
4345 
4346 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4347 struct _MatSolverTypeForSpecifcType {
4348   MatType mtype;
4349   /* no entry for MAT_FACTOR_NONE */
4350   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4351   MatSolverTypeForSpecifcType next;
4352 };
4353 
4354 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4355 struct _MatSolverTypeHolder {
4356   char                       *name;
4357   MatSolverTypeForSpecifcType handlers;
4358   MatSolverTypeHolder         next;
4359 };
4360 
4361 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4362 
4363 /*@C
4364    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4365 
4366    Input Parameters:
4367 +    package - name of the package, for example petsc or superlu
4368 .    mtype - the matrix type that works with this package
4369 .    ftype - the type of factorization supported by the package
4370 -    createfactor - routine that will create the factored matrix ready to be used
4371 
4372     Level: developer
4373 
4374 .seealso: `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4375 @*/
4376 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) {
4377   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4378   PetscBool                   flg;
4379   MatSolverTypeForSpecifcType inext, iprev = NULL;
4380 
4381   PetscFunctionBegin;
4382   PetscCall(MatInitializePackage());
4383   if (!next) {
4384     PetscCall(PetscNew(&MatSolverTypeHolders));
4385     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4386     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4387     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4388     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4389     PetscFunctionReturn(0);
4390   }
4391   while (next) {
4392     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4393     if (flg) {
4394       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4395       inext = next->handlers;
4396       while (inext) {
4397         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4398         if (flg) {
4399           inext->createfactor[(int)ftype - 1] = createfactor;
4400           PetscFunctionReturn(0);
4401         }
4402         iprev = inext;
4403         inext = inext->next;
4404       }
4405       PetscCall(PetscNew(&iprev->next));
4406       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4407       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4408       PetscFunctionReturn(0);
4409     }
4410     prev = next;
4411     next = next->next;
4412   }
4413   PetscCall(PetscNew(&prev->next));
4414   PetscCall(PetscStrallocpy(package, &prev->next->name));
4415   PetscCall(PetscNew(&prev->next->handlers));
4416   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4417   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4418   PetscFunctionReturn(0);
4419 }
4420 
4421 /*@C
4422    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4423 
4424    Input Parameters:
4425 +    type - name of the package, for example petsc or superlu
4426 .    ftype - the type of factorization supported by the type
4427 -    mtype - the matrix type that works with this type
4428 
4429    Output Parameters:
4430 +   foundtype - `PETSC_TRUE` if the type was registered
4431 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4432 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4433 
4434     Level: developer
4435 
4436 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4437 @*/
4438 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) {
4439   MatSolverTypeHolder         next = MatSolverTypeHolders;
4440   PetscBool                   flg;
4441   MatSolverTypeForSpecifcType inext;
4442 
4443   PetscFunctionBegin;
4444   if (foundtype) *foundtype = PETSC_FALSE;
4445   if (foundmtype) *foundmtype = PETSC_FALSE;
4446   if (createfactor) *createfactor = NULL;
4447 
4448   if (type) {
4449     while (next) {
4450       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4451       if (flg) {
4452         if (foundtype) *foundtype = PETSC_TRUE;
4453         inext = next->handlers;
4454         while (inext) {
4455           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4456           if (flg) {
4457             if (foundmtype) *foundmtype = PETSC_TRUE;
4458             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4459             PetscFunctionReturn(0);
4460           }
4461           inext = inext->next;
4462         }
4463       }
4464       next = next->next;
4465     }
4466   } else {
4467     while (next) {
4468       inext = next->handlers;
4469       while (inext) {
4470         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4471         if (flg && inext->createfactor[(int)ftype - 1]) {
4472           if (foundtype) *foundtype = PETSC_TRUE;
4473           if (foundmtype) *foundmtype = PETSC_TRUE;
4474           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4475           PetscFunctionReturn(0);
4476         }
4477         inext = inext->next;
4478       }
4479       next = next->next;
4480     }
4481     /* try with base classes inext->mtype */
4482     next = MatSolverTypeHolders;
4483     while (next) {
4484       inext = next->handlers;
4485       while (inext) {
4486         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4487         if (flg && inext->createfactor[(int)ftype - 1]) {
4488           if (foundtype) *foundtype = PETSC_TRUE;
4489           if (foundmtype) *foundmtype = PETSC_TRUE;
4490           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4491           PetscFunctionReturn(0);
4492         }
4493         inext = inext->next;
4494       }
4495       next = next->next;
4496     }
4497   }
4498   PetscFunctionReturn(0);
4499 }
4500 
4501 PetscErrorCode MatSolverTypeDestroy(void) {
4502   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4503   MatSolverTypeForSpecifcType inext, iprev;
4504 
4505   PetscFunctionBegin;
4506   while (next) {
4507     PetscCall(PetscFree(next->name));
4508     inext = next->handlers;
4509     while (inext) {
4510       PetscCall(PetscFree(inext->mtype));
4511       iprev = inext;
4512       inext = inext->next;
4513       PetscCall(PetscFree(iprev));
4514     }
4515     prev = next;
4516     next = next->next;
4517     PetscCall(PetscFree(prev));
4518   }
4519   MatSolverTypeHolders = NULL;
4520   PetscFunctionReturn(0);
4521 }
4522 
4523 /*@C
4524    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4525 
4526    Logically Collective on mat
4527 
4528    Input Parameters:
4529 .  mat - the matrix
4530 
4531    Output Parameters:
4532 .  flg - `PETSC_TRUE` if uses the ordering
4533 
4534    Note:
4535    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4536    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4537 
4538    Level: developer
4539 
4540 .seealso: `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4541 @*/
4542 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) {
4543   PetscFunctionBegin;
4544   *flg = mat->canuseordering;
4545   PetscFunctionReturn(0);
4546 }
4547 
4548 /*@C
4549    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4550 
4551    Logically Collective on mat
4552 
4553    Input Parameters:
4554 .  mat - the matrix obtained with `MatGetFactor()`
4555 
4556    Output Parameters:
4557 .  otype - the preferred type
4558 
4559    Level: developer
4560 
4561 .seealso: `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4562 @*/
4563 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) {
4564   PetscFunctionBegin;
4565   *otype = mat->preferredordering[ftype];
4566   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4567   PetscFunctionReturn(0);
4568 }
4569 
4570 /*@C
4571    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4572 
4573    Collective on mat
4574 
4575    Input Parameters:
4576 +  mat - the matrix
4577 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4578 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4579 
4580    Output Parameters:
4581 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4582 
4583    Options Database Key:
4584 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4585                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4586 
4587    Notes:
4588      Users usually access the factorization solvers via `KSP`
4589 
4590       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4591      such as pastix, superlu, mumps etc.
4592 
4593       PETSc must have been ./configure to use the external solver, using the option --download-package
4594 
4595       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4596       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4597       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4598 
4599    Developer Note:
4600       This should actually be called `MatCreateFactor()` since it creates a new factor object
4601 
4602    Level: intermediate
4603 
4604 .seealso: `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4605           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4606 @*/
4607 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) {
4608   PetscBool foundtype, foundmtype;
4609   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4610 
4611   PetscFunctionBegin;
4612   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4613   PetscValidType(mat, 1);
4614 
4615   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4616   MatCheckPreallocated(mat, 1);
4617 
4618   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4619   if (!foundtype) {
4620     if (type) {
4621       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],
4622               ((PetscObject)mat)->type_name, type);
4623     } else {
4624       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);
4625     }
4626   }
4627   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4628   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);
4629 
4630   PetscCall((*conv)(mat, ftype, f));
4631   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4632   PetscFunctionReturn(0);
4633 }
4634 
4635 /*@C
4636    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4637 
4638    Not Collective
4639 
4640    Input Parameters:
4641 +  mat - the matrix
4642 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4643 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4644 
4645    Output Parameter:
4646 .    flg - PETSC_TRUE if the factorization is available
4647 
4648    Notes:
4649       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4650      such as pastix, superlu, mumps etc.
4651 
4652       PETSc must have been ./configure to use the external solver, using the option --download-package
4653 
4654    Developer Note:
4655       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4656 
4657    Level: intermediate
4658 
4659 .seealso: `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4660           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4661 @*/
4662 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) {
4663   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4664 
4665   PetscFunctionBegin;
4666   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4667   PetscValidType(mat, 1);
4668   PetscValidBoolPointer(flg, 4);
4669 
4670   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4671   MatCheckPreallocated(mat, 1);
4672 
4673   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4674   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4675   PetscFunctionReturn(0);
4676 }
4677 
4678 /*@
4679    MatDuplicate - Duplicates a matrix including the non-zero structure.
4680 
4681    Collective on mat
4682 
4683    Input Parameters:
4684 +  mat - the matrix
4685 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4686         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4687 
4688    Output Parameter:
4689 .  M - pointer to place new matrix
4690 
4691    Level: intermediate
4692 
4693    Notes:
4694     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4695 
4696     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.
4697 
4698     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
4699     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4700     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4701 
4702 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4703 @*/
4704 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) {
4705   Mat         B;
4706   VecType     vtype;
4707   PetscInt    i;
4708   PetscObject dm;
4709   void (*viewf)(void);
4710 
4711   PetscFunctionBegin;
4712   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4713   PetscValidType(mat, 1);
4714   PetscValidPointer(M, 3);
4715   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4716   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4717   MatCheckPreallocated(mat, 1);
4718 
4719   *M = NULL;
4720   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4721   PetscUseTypeMethod(mat, duplicate, op, M);
4722   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4723   B = *M;
4724 
4725   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4726   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4727   PetscCall(MatGetVecType(mat, &vtype));
4728   PetscCall(MatSetVecType(B, vtype));
4729 
4730   B->stencil.dim = mat->stencil.dim;
4731   B->stencil.noc = mat->stencil.noc;
4732   for (i = 0; i <= mat->stencil.dim; i++) {
4733     B->stencil.dims[i]   = mat->stencil.dims[i];
4734     B->stencil.starts[i] = mat->stencil.starts[i];
4735   }
4736 
4737   B->nooffproczerorows = mat->nooffproczerorows;
4738   B->nooffprocentries  = mat->nooffprocentries;
4739 
4740   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4741   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4742   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4743   PetscFunctionReturn(0);
4744 }
4745 
4746 /*@
4747    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4748 
4749    Logically Collective on mat
4750 
4751    Input Parameters:
4752 +  mat - the matrix
4753 -  v - the vector for storing the diagonal
4754 
4755    Output Parameter:
4756 .  v - the diagonal of the matrix
4757 
4758    Level: intermediate
4759 
4760    Note:
4761    Currently only correct in parallel for square matrices.
4762 
4763 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4764 @*/
4765 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) {
4766   PetscFunctionBegin;
4767   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4768   PetscValidType(mat, 1);
4769   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4770   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4771   MatCheckPreallocated(mat, 1);
4772 
4773   PetscUseTypeMethod(mat, getdiagonal, v);
4774   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4775   PetscFunctionReturn(0);
4776 }
4777 
4778 /*@C
4779    MatGetRowMin - Gets the minimum value (of the real part) of each
4780         row of the matrix
4781 
4782    Logically Collective on mat
4783 
4784    Input Parameter:
4785 .  mat - the matrix
4786 
4787    Output Parameters:
4788 +  v - the vector for storing the maximums
4789 -  idx - the indices of the column found for each row (optional)
4790 
4791    Level: intermediate
4792 
4793    Note:
4794     The result of this call are the same as if one converted the matrix to dense format
4795       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4796 
4797     This code is only implemented for a couple of matrix formats.
4798 
4799 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4800           `MatGetRowMax()`
4801 @*/
4802 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) {
4803   PetscFunctionBegin;
4804   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4805   PetscValidType(mat, 1);
4806   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4807   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4808 
4809   if (!mat->cmap->N) {
4810     PetscCall(VecSet(v, PETSC_MAX_REAL));
4811     if (idx) {
4812       PetscInt i, m = mat->rmap->n;
4813       for (i = 0; i < m; i++) idx[i] = -1;
4814     }
4815   } else {
4816     MatCheckPreallocated(mat, 1);
4817   }
4818   PetscUseTypeMethod(mat, getrowmin, v, idx);
4819   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4820   PetscFunctionReturn(0);
4821 }
4822 
4823 /*@C
4824    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4825         row of the matrix
4826 
4827    Logically Collective on mat
4828 
4829    Input Parameter:
4830 .  mat - the matrix
4831 
4832    Output Parameters:
4833 +  v - the vector for storing the minimums
4834 -  idx - the indices of the column found for each row (or NULL if not needed)
4835 
4836    Level: intermediate
4837 
4838    Notes:
4839     if a row is completely empty or has only 0.0 values then the idx[] value for that
4840     row is 0 (the first column).
4841 
4842     This code is only implemented for a couple of matrix formats.
4843 
4844 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4845 @*/
4846 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) {
4847   PetscFunctionBegin;
4848   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4849   PetscValidType(mat, 1);
4850   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4851   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4852   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4853 
4854   if (!mat->cmap->N) {
4855     PetscCall(VecSet(v, 0.0));
4856     if (idx) {
4857       PetscInt i, m = mat->rmap->n;
4858       for (i = 0; i < m; i++) idx[i] = -1;
4859     }
4860   } else {
4861     MatCheckPreallocated(mat, 1);
4862     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4863     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4864   }
4865   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4866   PetscFunctionReturn(0);
4867 }
4868 
4869 /*@C
4870    MatGetRowMax - Gets the maximum value (of the real part) of each
4871         row of the matrix
4872 
4873    Logically Collective on mat
4874 
4875    Input Parameter:
4876 .  mat - the matrix
4877 
4878    Output Parameters:
4879 +  v - the vector for storing the maximums
4880 -  idx - the indices of the column found for each row (optional)
4881 
4882    Level: intermediate
4883 
4884    Notes:
4885     The result of this call are the same as if one converted the matrix to dense format
4886       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4887 
4888     This code is only implemented for a couple of matrix formats.
4889 
4890 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4891 @*/
4892 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) {
4893   PetscFunctionBegin;
4894   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4895   PetscValidType(mat, 1);
4896   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4897   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4898 
4899   if (!mat->cmap->N) {
4900     PetscCall(VecSet(v, PETSC_MIN_REAL));
4901     if (idx) {
4902       PetscInt i, m = mat->rmap->n;
4903       for (i = 0; i < m; i++) idx[i] = -1;
4904     }
4905   } else {
4906     MatCheckPreallocated(mat, 1);
4907     PetscUseTypeMethod(mat, getrowmax, v, idx);
4908   }
4909   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4910   PetscFunctionReturn(0);
4911 }
4912 
4913 /*@C
4914    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4915         row of the matrix
4916 
4917    Logically Collective on mat
4918 
4919    Input Parameter:
4920 .  mat - the matrix
4921 
4922    Output Parameters:
4923 +  v - the vector for storing the maximums
4924 -  idx - the indices of the column found for each row (or NULL if not needed)
4925 
4926    Level: intermediate
4927 
4928    Notes:
4929     if a row is completely empty or has only 0.0 values then the idx[] value for that
4930     row is 0 (the first column).
4931 
4932     This code is only implemented for a couple of matrix formats.
4933 
4934 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4935 @*/
4936 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) {
4937   PetscFunctionBegin;
4938   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4939   PetscValidType(mat, 1);
4940   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4941   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4942 
4943   if (!mat->cmap->N) {
4944     PetscCall(VecSet(v, 0.0));
4945     if (idx) {
4946       PetscInt i, m = mat->rmap->n;
4947       for (i = 0; i < m; i++) idx[i] = -1;
4948     }
4949   } else {
4950     MatCheckPreallocated(mat, 1);
4951     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4952     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
4953   }
4954   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4955   PetscFunctionReturn(0);
4956 }
4957 
4958 /*@
4959    MatGetRowSum - Gets the sum of each row of the matrix
4960 
4961    Logically or Neighborhood Collective on mat
4962 
4963    Input Parameters:
4964 .  mat - the matrix
4965 
4966    Output Parameter:
4967 .  v - the vector for storing the sum of rows
4968 
4969    Level: intermediate
4970 
4971    Notes:
4972     This code is slow since it is not currently specialized for different formats
4973 
4974 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
4975 @*/
4976 PetscErrorCode MatGetRowSum(Mat mat, Vec v) {
4977   Vec ones;
4978 
4979   PetscFunctionBegin;
4980   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4981   PetscValidType(mat, 1);
4982   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4983   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4984   MatCheckPreallocated(mat, 1);
4985   PetscCall(MatCreateVecs(mat, &ones, NULL));
4986   PetscCall(VecSet(ones, 1.));
4987   PetscCall(MatMult(mat, ones, v));
4988   PetscCall(VecDestroy(&ones));
4989   PetscFunctionReturn(0);
4990 }
4991 
4992 /*@
4993    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
4994    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
4995 
4996    Collective on mat
4997 
4998    Input Parameter:
4999 .  mat - the matrix to provide the transpose
5000 
5001    Output Parameter:
5002 .  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
5003 
5004    Level: advanced
5005 
5006    Note:
5007    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
5008    routine allows bypassing that call.
5009 
5010 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5011 @*/
5012 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) {
5013   PetscContainer  rB = NULL;
5014   MatParentState *rb = NULL;
5015 
5016   PetscFunctionBegin;
5017   PetscCall(PetscNew(&rb));
5018   rb->id    = ((PetscObject)mat)->id;
5019   rb->state = 0;
5020   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5021   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5022   PetscCall(PetscContainerSetPointer(rB, rb));
5023   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5024   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5025   PetscCall(PetscObjectDereference((PetscObject)rB));
5026   PetscFunctionReturn(0);
5027 }
5028 
5029 /*@
5030    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5031 
5032    Collective on mat
5033 
5034    Input Parameters:
5035 +  mat - the matrix to transpose
5036 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5037 
5038    Output Parameter:
5039 .  B - the transpose
5040 
5041    Notes:
5042      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5043 
5044      `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
5045      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5046 
5047      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.
5048 
5049      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5050 
5051      If mat is unchanged from the last call this function returns immediately without recomputing the result
5052 
5053      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5054 
5055    Level: intermediate
5056 
5057 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5058           `MatTransposeSymbolic()`
5059 @*/
5060 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) {
5061   PetscContainer  rB = NULL;
5062   MatParentState *rb = NULL;
5063 
5064   PetscFunctionBegin;
5065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5066   PetscValidType(mat, 1);
5067   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5068   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5069   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5070   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5071   MatCheckPreallocated(mat, 1);
5072   if (reuse == MAT_REUSE_MATRIX) {
5073     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5074     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5075     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5076     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5077     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0);
5078   }
5079 
5080   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5081   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5082     PetscUseTypeMethod(mat, transpose, reuse, B);
5083     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5084   }
5085   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5086 
5087   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5088   if (reuse != MAT_INPLACE_MATRIX) {
5089     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5090     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5091     rb->state        = ((PetscObject)mat)->state;
5092     rb->nonzerostate = mat->nonzerostate;
5093   }
5094   PetscFunctionReturn(0);
5095 }
5096 
5097 /*@
5098    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5099 
5100    Collective on A
5101 
5102    Input Parameters:
5103 .  A - the matrix to transpose
5104 
5105    Output Parameter:
5106 .  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
5107       numerical portion.
5108 
5109    Level: intermediate
5110 
5111    Note:
5112    This is not supported for many matrix types, use `MatTranspose()` in those cases
5113 
5114 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5115 @*/
5116 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) {
5117   PetscFunctionBegin;
5118   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5119   PetscValidType(A, 1);
5120   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5121   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5122   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5123   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5124   PetscCall((*A->ops->transposesymbolic)(A, B));
5125   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5126 
5127   PetscCall(MatTransposeSetPrecursor(A, *B));
5128   PetscFunctionReturn(0);
5129 }
5130 
5131 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) {
5132   PetscContainer  rB;
5133   MatParentState *rb;
5134 
5135   PetscFunctionBegin;
5136   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5137   PetscValidType(A, 1);
5138   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5139   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5140   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5141   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5142   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5143   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5144   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5145   PetscFunctionReturn(0);
5146 }
5147 
5148 /*@
5149    MatIsTranspose - Test whether a matrix is another one's transpose,
5150         or its own, in which case it tests symmetry.
5151 
5152    Collective on A
5153 
5154    Input Parameters:
5155 +  A - the matrix to test
5156 -  B - the matrix to test against, this can equal the first parameter
5157 
5158    Output Parameters:
5159 .  flg - the result
5160 
5161    Notes:
5162    Only available for `MATAIJ` matrices.
5163 
5164    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5165    test involves parallel copies of the block-offdiagonal parts of the matrix.
5166 
5167    Level: intermediate
5168 
5169 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5170 @*/
5171 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) {
5172   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5173 
5174   PetscFunctionBegin;
5175   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5176   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5177   PetscValidBoolPointer(flg, 4);
5178   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5179   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5180   *flg = PETSC_FALSE;
5181   if (f && g) {
5182     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5183     PetscCall((*f)(A, B, tol, flg));
5184   } else {
5185     MatType mattype;
5186 
5187     PetscCall(MatGetType(f ? B : A, &mattype));
5188     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5189   }
5190   PetscFunctionReturn(0);
5191 }
5192 
5193 /*@
5194    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5195 
5196    Collective on mat
5197 
5198    Input Parameters:
5199 +  mat - the matrix to transpose and complex conjugate
5200 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5201 
5202    Output Parameter:
5203 .  B - the Hermitian transpose
5204 
5205    Level: intermediate
5206 
5207 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5208 @*/
5209 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) {
5210   PetscFunctionBegin;
5211   PetscCall(MatTranspose(mat, reuse, B));
5212 #if defined(PETSC_USE_COMPLEX)
5213   PetscCall(MatConjugate(*B));
5214 #endif
5215   PetscFunctionReturn(0);
5216 }
5217 
5218 /*@
5219    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5220 
5221    Collective on A
5222 
5223    Input Parameters:
5224 +  A - the matrix to test
5225 -  B - the matrix to test against, this can equal the first parameter
5226 
5227    Output Parameters:
5228 .  flg - the result
5229 
5230    Notes:
5231    Only available for `MATAIJ` matrices.
5232 
5233    The sequential algorithm
5234    has a running time of the order of the number of nonzeros; the parallel
5235    test involves parallel copies of the block-offdiagonal parts of the matrix.
5236 
5237    Level: intermediate
5238 
5239 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5240 @*/
5241 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) {
5242   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5243 
5244   PetscFunctionBegin;
5245   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5246   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5247   PetscValidBoolPointer(flg, 4);
5248   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5249   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5250   if (f && g) {
5251     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5252     PetscCall((*f)(A, B, tol, flg));
5253   }
5254   PetscFunctionReturn(0);
5255 }
5256 
5257 /*@
5258    MatPermute - Creates a new matrix with rows and columns permuted from the
5259    original.
5260 
5261    Collective on mat
5262 
5263    Input Parameters:
5264 +  mat - the matrix to permute
5265 .  row - row permutation, each processor supplies only the permutation for its rows
5266 -  col - column permutation, each processor supplies only the permutation for its columns
5267 
5268    Output Parameters:
5269 .  B - the permuted matrix
5270 
5271    Level: advanced
5272 
5273    Note:
5274    The index sets map from row/col of permuted matrix to row/col of original matrix.
5275    The index sets should be on the same communicator as mat and have the same local sizes.
5276 
5277    Developer Note:
5278      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5279      exploit the fact that row and col are permutations, consider implementing the
5280      more general `MatCreateSubMatrix()` instead.
5281 
5282 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5283 @*/
5284 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) {
5285   PetscFunctionBegin;
5286   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5287   PetscValidType(mat, 1);
5288   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5289   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5290   PetscValidPointer(B, 4);
5291   PetscCheckSameComm(mat, 1, row, 2);
5292   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5293   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5294   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5295   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5296   MatCheckPreallocated(mat, 1);
5297 
5298   if (mat->ops->permute) {
5299     PetscUseTypeMethod(mat, permute, row, col, B);
5300     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5301   } else {
5302     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5303   }
5304   PetscFunctionReturn(0);
5305 }
5306 
5307 /*@
5308    MatEqual - Compares two matrices.
5309 
5310    Collective on A
5311 
5312    Input Parameters:
5313 +  A - the first matrix
5314 -  B - the second matrix
5315 
5316    Output Parameter:
5317 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5318 
5319    Level: intermediate
5320 
5321 .seealso: `Mat`
5322 @*/
5323 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) {
5324   PetscFunctionBegin;
5325   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5326   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5327   PetscValidType(A, 1);
5328   PetscValidType(B, 2);
5329   PetscValidBoolPointer(flg, 3);
5330   PetscCheckSameComm(A, 1, B, 2);
5331   MatCheckPreallocated(A, 1);
5332   MatCheckPreallocated(B, 2);
5333   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5334   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5335   PetscCheck(A->rmap->N == B->rmap->N && A->cmap->N == B->cmap->N, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_SIZ, "Mat A,Mat B: global dim %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT " %" PetscInt_FMT, A->rmap->N, B->rmap->N, A->cmap->N,
5336              B->cmap->N);
5337   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5338     PetscUseTypeMethod(A, equal, B, flg);
5339   } else {
5340     PetscCall(MatMultEqual(A, B, 10, flg));
5341   }
5342   PetscFunctionReturn(0);
5343 }
5344 
5345 /*@
5346    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5347    matrices that are stored as vectors.  Either of the two scaling
5348    matrices can be NULL.
5349 
5350    Collective on mat
5351 
5352    Input Parameters:
5353 +  mat - the matrix to be scaled
5354 .  l - the left scaling vector (or NULL)
5355 -  r - the right scaling vector (or NULL)
5356 
5357    Note:
5358    `MatDiagonalScale()` computes A = LAR, where
5359    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5360    The L scales the rows of the matrix, the R scales the columns of the matrix.
5361 
5362    Level: intermediate
5363 
5364 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5365 @*/
5366 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) {
5367   PetscFunctionBegin;
5368   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5369   PetscValidType(mat, 1);
5370   if (l) {
5371     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5372     PetscCheckSameComm(mat, 1, l, 2);
5373   }
5374   if (r) {
5375     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5376     PetscCheckSameComm(mat, 1, r, 3);
5377   }
5378   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5379   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5380   MatCheckPreallocated(mat, 1);
5381   if (!l && !r) PetscFunctionReturn(0);
5382 
5383   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5384   PetscUseTypeMethod(mat, diagonalscale, l, r);
5385   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5386   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5387   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5388   PetscFunctionReturn(0);
5389 }
5390 
5391 /*@
5392     MatScale - Scales all elements of a matrix by a given number.
5393 
5394     Logically Collective on mat
5395 
5396     Input Parameters:
5397 +   mat - the matrix to be scaled
5398 -   a  - the scaling value
5399 
5400     Output Parameter:
5401 .   mat - the scaled matrix
5402 
5403     Level: intermediate
5404 
5405 .seealso: `Mat`, `MatDiagonalScale()`
5406 @*/
5407 PetscErrorCode MatScale(Mat mat, PetscScalar a) {
5408   PetscFunctionBegin;
5409   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5410   PetscValidType(mat, 1);
5411   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5412   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5413   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5414   PetscValidLogicalCollectiveScalar(mat, a, 2);
5415   MatCheckPreallocated(mat, 1);
5416 
5417   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5418   if (a != (PetscScalar)1.0) {
5419     PetscUseTypeMethod(mat, scale, a);
5420     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5421   }
5422   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5423   PetscFunctionReturn(0);
5424 }
5425 
5426 /*@
5427    MatNorm - Calculates various norms of a matrix.
5428 
5429    Collective on mat
5430 
5431    Input Parameters:
5432 +  mat - the matrix
5433 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5434 
5435    Output Parameter:
5436 .  nrm - the resulting norm
5437 
5438    Level: intermediate
5439 
5440 .seealso: `Mat`
5441 @*/
5442 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) {
5443   PetscFunctionBegin;
5444   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5445   PetscValidType(mat, 1);
5446   PetscValidRealPointer(nrm, 3);
5447 
5448   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5449   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5450   MatCheckPreallocated(mat, 1);
5451 
5452   PetscUseTypeMethod(mat, norm, type, nrm);
5453   PetscFunctionReturn(0);
5454 }
5455 
5456 /*
5457      This variable is used to prevent counting of MatAssemblyBegin() that
5458    are called from within a MatAssemblyEnd().
5459 */
5460 static PetscInt MatAssemblyEnd_InUse = 0;
5461 /*@
5462    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5463    be called after completing all calls to `MatSetValues()`.
5464 
5465    Collective on mat
5466 
5467    Input Parameters:
5468 +  mat - the matrix
5469 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5470 
5471    Notes:
5472    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5473    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5474 
5475    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5476    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5477    using the matrix.
5478 
5479    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5480    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
5481    a global collective operation requring all processes that share the matrix.
5482 
5483    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5484    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5485    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5486 
5487    Level: beginner
5488 
5489 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5490 @*/
5491 PetscErrorCode  MatAssemblyBegin(Mat mat, MatAssemblyType type) {
5492    PetscFunctionBegin;
5493    PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5494    PetscValidType(mat, 1);
5495    MatCheckPreallocated(mat, 1);
5496    PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5497    if (mat->assembled) {
5498      mat->was_assembled = PETSC_TRUE;
5499      mat->assembled     = PETSC_FALSE;
5500   }
5501 
5502    if (!MatAssemblyEnd_InUse) {
5503      PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5504      PetscTryTypeMethod(mat, assemblybegin, type);
5505      PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5506   } else PetscTryTypeMethod(mat, assemblybegin, type);
5507    PetscFunctionReturn(0);
5508 }
5509 
5510 /*@
5511    MatAssembled - Indicates if a matrix has been assembled and is ready for
5512      use; for example, in matrix-vector product.
5513 
5514    Not Collective
5515 
5516    Input Parameter:
5517 .  mat - the matrix
5518 
5519    Output Parameter:
5520 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5521 
5522    Level: advanced
5523 
5524 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5525 @*/
5526 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) {
5527   PetscFunctionBegin;
5528   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5529   PetscValidBoolPointer(assembled, 2);
5530   *assembled = mat->assembled;
5531   PetscFunctionReturn(0);
5532 }
5533 
5534 /*@
5535    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5536    be called after `MatAssemblyBegin()`.
5537 
5538    Collective on Mat
5539 
5540    Input Parameters:
5541 +  mat - the matrix
5542 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5543 
5544    Options Database Keys:
5545 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5546 .  -mat_view ::ascii_info_detail - Prints more detailed info
5547 .  -mat_view - Prints matrix in ASCII format
5548 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5549 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5550 .  -display <name> - Sets display name (default is host)
5551 .  -draw_pause <sec> - Sets number of seconds to pause after display
5552 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See Users-Manual: ch_matlab)
5553 .  -viewer_socket_machine <machine> - Machine to use for socket
5554 .  -viewer_socket_port <port> - Port number to use for socket
5555 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5556 
5557    Level: beginner
5558 
5559 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5560 @*/
5561 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) {
5562   static PetscInt inassm = 0;
5563   PetscBool       flg    = PETSC_FALSE;
5564 
5565   PetscFunctionBegin;
5566   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5567   PetscValidType(mat, 1);
5568 
5569   inassm++;
5570   MatAssemblyEnd_InUse++;
5571   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5572     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5573     PetscTryTypeMethod(mat, assemblyend, type);
5574     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5575   } else PetscTryTypeMethod(mat, assemblyend, type);
5576 
5577   /* Flush assembly is not a true assembly */
5578   if (type != MAT_FLUSH_ASSEMBLY) {
5579     if (mat->num_ass) {
5580       if (!mat->symmetry_eternal) {
5581         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5582         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5583       }
5584       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5585       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5586     }
5587     mat->num_ass++;
5588     mat->assembled        = PETSC_TRUE;
5589     mat->ass_nonzerostate = mat->nonzerostate;
5590   }
5591 
5592   mat->insertmode = NOT_SET_VALUES;
5593   MatAssemblyEnd_InUse--;
5594   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5595   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5596     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5597 
5598     if (mat->checksymmetryonassembly) {
5599       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5600       if (flg) {
5601         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5602       } else {
5603         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5604       }
5605     }
5606     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5607   }
5608   inassm--;
5609   PetscFunctionReturn(0);
5610 }
5611 
5612 /*@
5613    MatSetOption - Sets a parameter option for a matrix. Some options
5614    may be specific to certain storage formats.  Some options
5615    determine how values will be inserted (or added). Sorted,
5616    row-oriented input will generally assemble the fastest. The default
5617    is row-oriented.
5618 
5619    Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5620 
5621    Input Parameters:
5622 +  mat - the matrix
5623 .  option - the option, one of those listed below (and possibly others),
5624 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5625 
5626   Options Describing Matrix Structure:
5627 +    `MAT_SPD` - symmetric positive definite
5628 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5629 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5630 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5631 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5632 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5633 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5634 
5635    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5636    do not need to be computed (usually at a high cost)
5637 
5638    Options For Use with `MatSetValues()`:
5639    Insert a logically dense subblock, which can be
5640 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5641 
5642    Note these options reflect the data you pass in with `MatSetValues()`; it has
5643    nothing to do with how the data is stored internally in the matrix
5644    data structure.
5645 
5646    When (re)assembling a matrix, we can restrict the input for
5647    efficiency/debugging purposes.  These options include
5648 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5649 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5650 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5651 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5652 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5653 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5654         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5655         performance for very large process counts.
5656 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5657         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5658         functions, instead sending only neighbor messages.
5659 
5660    Notes:
5661    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5662 
5663    Some options are relevant only for particular matrix types and
5664    are thus ignored by others.  Other options are not supported by
5665    certain matrix types and will generate an error message if set.
5666 
5667    If using a Fortran 77 module to compute a matrix, one may need to
5668    use the column-oriented option (or convert to the row-oriented
5669    format).
5670 
5671    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5672    that would generate a new entry in the nonzero structure is instead
5673    ignored.  Thus, if memory has not alredy been allocated for this particular
5674    data, then the insertion is ignored. For dense matrices, in which
5675    the entire array is allocated, no entries are ever ignored.
5676    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5677 
5678    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5679    that would generate a new entry in the nonzero structure instead produces
5680    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
5681 
5682    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5683    that would generate a new entry that has not been preallocated will
5684    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5685    only.) This is a useful flag when debugging matrix memory preallocation.
5686    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5687 
5688    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5689    other processors should be dropped, rather than stashed.
5690    This is useful if you know that the "owning" processor is also
5691    always generating the correct matrix entries, so that PETSc need
5692    not transfer duplicate entries generated on another processor.
5693 
5694    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5695    searches during matrix assembly. When this flag is set, the hash table
5696    is created during the first matrix assembly. This hash table is
5697    used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5698    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5699    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5700    supported by` MATMPIBAIJ` format only.
5701 
5702    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5703    are kept in the nonzero structure
5704 
5705    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5706    a zero location in the matrix
5707 
5708    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5709 
5710    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5711         zero row routines and thus improves performance for very large process counts.
5712 
5713    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5714         part of the matrix (since they should match the upper triangular part).
5715 
5716    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5717                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5718                      with finite difference schemes with non-periodic boundary conditions.
5719 
5720    Developer Note:
5721    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5722    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5723    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5724    not changed.
5725 
5726    Level: intermediate
5727 
5728 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5729 @*/
5730 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) {
5731   PetscFunctionBegin;
5732   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5733   if (op > 0) {
5734     PetscValidLogicalCollectiveEnum(mat, op, 2);
5735     PetscValidLogicalCollectiveBool(mat, flg, 3);
5736   }
5737 
5738   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);
5739 
5740   switch (op) {
5741   case MAT_FORCE_DIAGONAL_ENTRIES: mat->force_diagonals = flg; PetscFunctionReturn(0);
5742   case MAT_NO_OFF_PROC_ENTRIES: mat->nooffprocentries = flg; PetscFunctionReturn(0);
5743   case MAT_SUBSET_OFF_PROC_ENTRIES:
5744     mat->assembly_subset = flg;
5745     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5746 #if !defined(PETSC_HAVE_MPIUNI)
5747       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5748 #endif
5749       mat->stash.first_assembly_done = PETSC_FALSE;
5750     }
5751     PetscFunctionReturn(0);
5752   case MAT_NO_OFF_PROC_ZERO_ROWS: mat->nooffproczerorows = flg; PetscFunctionReturn(0);
5753   case MAT_SPD:
5754     if (flg) {
5755       mat->spd                    = PETSC_BOOL3_TRUE;
5756       mat->symmetric              = PETSC_BOOL3_TRUE;
5757       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5758     } else {
5759       mat->spd = PETSC_BOOL3_FALSE;
5760     }
5761     break;
5762   case MAT_SYMMETRIC:
5763     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5764     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5765 #if !defined(PETSC_USE_COMPLEX)
5766     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5767 #endif
5768     break;
5769   case MAT_HERMITIAN:
5770     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5771     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5772 #if !defined(PETSC_USE_COMPLEX)
5773     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5774 #endif
5775     break;
5776   case MAT_STRUCTURALLY_SYMMETRIC: mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; break;
5777   case MAT_SYMMETRY_ETERNAL:
5778     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");
5779     mat->symmetry_eternal = flg;
5780     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5781     break;
5782   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5783     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");
5784     mat->structural_symmetry_eternal = flg;
5785     break;
5786   case MAT_SPD_ETERNAL:
5787     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");
5788     mat->spd_eternal = flg;
5789     if (flg) {
5790       mat->structural_symmetry_eternal = PETSC_TRUE;
5791       mat->symmetry_eternal            = PETSC_TRUE;
5792     }
5793     break;
5794   case MAT_STRUCTURE_ONLY: mat->structure_only = flg; break;
5795   case MAT_SORTED_FULL: mat->sortedfull = flg; break;
5796   default: break;
5797   }
5798   PetscTryTypeMethod(mat, setoption, op, flg);
5799   PetscFunctionReturn(0);
5800 }
5801 
5802 /*@
5803    MatGetOption - Gets a parameter option that has been set for a matrix.
5804 
5805    Logically Collective on mat
5806 
5807    Input Parameters:
5808 +  mat - the matrix
5809 -  option - the option, this only responds to certain options, check the code for which ones
5810 
5811    Output Parameter:
5812 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5813 
5814     Notes:
5815     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5816 
5817     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`, or
5818     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5819 
5820    Level: intermediate
5821 
5822 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`,
5823     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5824 @*/
5825 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) {
5826   PetscFunctionBegin;
5827   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5828   PetscValidType(mat, 1);
5829 
5830   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);
5831   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()");
5832 
5833   switch (op) {
5834   case MAT_NO_OFF_PROC_ENTRIES: *flg = mat->nooffprocentries; break;
5835   case MAT_NO_OFF_PROC_ZERO_ROWS: *flg = mat->nooffproczerorows; break;
5836   case MAT_SYMMETRIC: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); break;
5837   case MAT_HERMITIAN: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); break;
5838   case MAT_STRUCTURALLY_SYMMETRIC: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); break;
5839   case MAT_SPD: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); break;
5840   case MAT_SYMMETRY_ETERNAL: *flg = mat->symmetry_eternal; break;
5841   case MAT_STRUCTURAL_SYMMETRY_ETERNAL: *flg = mat->symmetry_eternal; break;
5842   default: break;
5843   }
5844   PetscFunctionReturn(0);
5845 }
5846 
5847 /*@
5848    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5849    this routine retains the old nonzero structure.
5850 
5851    Logically Collective on mat
5852 
5853    Input Parameters:
5854 .  mat - the matrix
5855 
5856    Level: intermediate
5857 
5858    Note:
5859     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.
5860    See the Performance chapter of the users manual for information on preallocating matrices.
5861 
5862 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5863 @*/
5864 PetscErrorCode MatZeroEntries(Mat mat) {
5865   PetscFunctionBegin;
5866   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5867   PetscValidType(mat, 1);
5868   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5869   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");
5870   MatCheckPreallocated(mat, 1);
5871 
5872   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
5873   PetscUseTypeMethod(mat, zeroentries);
5874   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
5875   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5876   PetscFunctionReturn(0);
5877 }
5878 
5879 /*@
5880    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5881    of a set of rows and columns of a matrix.
5882 
5883    Collective on mat
5884 
5885    Input Parameters:
5886 +  mat - the matrix
5887 .  numRows - the number of rows to remove
5888 .  rows - the global row indices
5889 .  diag - value put in the diagonal of the eliminated rows
5890 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5891 -  b - optional vector of right hand side, that will be adjusted by provided solution
5892 
5893    Notes:
5894    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5895 
5896    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5897    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
5898 
5899    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5900    Krylov method to take advantage of the known solution on the zeroed rows.
5901 
5902    For the parallel case, all processes that share the matrix (i.e.,
5903    those in the communicator used for matrix creation) MUST call this
5904    routine, regardless of whether any rows being zeroed are owned by
5905    them.
5906 
5907    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5908 
5909    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5910    list only rows local to itself).
5911 
5912    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
5913 
5914    Level: intermediate
5915 
5916 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5917           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5918 @*/
5919 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
5920   PetscFunctionBegin;
5921   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5922   PetscValidType(mat, 1);
5923   if (numRows) PetscValidIntPointer(rows, 3);
5924   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5925   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5926   MatCheckPreallocated(mat, 1);
5927 
5928   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5929   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5930   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5931   PetscFunctionReturn(0);
5932 }
5933 
5934 /*@
5935    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5936    of a set of rows and columns of a matrix.
5937 
5938    Collective on mat
5939 
5940    Input Parameters:
5941 +  mat - the matrix
5942 .  is - the rows to zero
5943 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5944 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5945 -  b - optional vector of right hand side, that will be adjusted by provided solution
5946 
5947    Note:
5948    See `MatZeroRowsColumns()` for details on how this routine operates.
5949 
5950    Level: intermediate
5951 
5952 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5953           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
5954 @*/
5955 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
5956   PetscInt        numRows;
5957   const PetscInt *rows;
5958 
5959   PetscFunctionBegin;
5960   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5961   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
5962   PetscValidType(mat, 1);
5963   PetscValidType(is, 2);
5964   PetscCall(ISGetLocalSize(is, &numRows));
5965   PetscCall(ISGetIndices(is, &rows));
5966   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
5967   PetscCall(ISRestoreIndices(is, &rows));
5968   PetscFunctionReturn(0);
5969 }
5970 
5971 /*@
5972    MatZeroRows - Zeros all entries (except possibly the main diagonal)
5973    of a set of rows of a matrix.
5974 
5975    Collective on mat
5976 
5977    Input Parameters:
5978 +  mat - the matrix
5979 .  numRows - the number of rows to remove
5980 .  rows - the global row indices
5981 .  diag - value put in the diagonal of the eliminated rows
5982 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5983 -  b - optional vector of right hand side, that will be adjusted by provided solution
5984 
5985    Notes:
5986    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5987 
5988    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5989 
5990    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5991    Krylov method to take advantage of the known solution on the zeroed rows.
5992 
5993    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)
5994    from the matrix.
5995 
5996    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
5997    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
5998    formats this does not alter the nonzero structure.
5999 
6000    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6001    of the matrix is not changed the values are
6002    merely zeroed.
6003 
6004    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6005    formats can optionally remove the main diagonal entry from the
6006    nonzero structure as well, by passing 0.0 as the final argument).
6007 
6008    For the parallel case, all processes that share the matrix (i.e.,
6009    those in the communicator used for matrix creation) MUST call this
6010    routine, regardless of whether any rows being zeroed are owned by
6011    them.
6012 
6013    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6014    list only rows local to itself).
6015 
6016    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6017    owns that are to be zeroed. This saves a global synchronization in the implementation.
6018 
6019    Level: intermediate
6020 
6021 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6022           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6023 @*/
6024 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6025   PetscFunctionBegin;
6026   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6027   PetscValidType(mat, 1);
6028   if (numRows) PetscValidIntPointer(rows, 3);
6029   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6030   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6031   MatCheckPreallocated(mat, 1);
6032 
6033   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6034   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6035   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6036   PetscFunctionReturn(0);
6037 }
6038 
6039 /*@
6040    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6041    of a set of rows of a matrix.
6042 
6043    Collective on Mat
6044 
6045    Input Parameters:
6046 +  mat - the matrix
6047 .  is - index set of rows to remove (if NULL then no row is removed)
6048 .  diag - value put in all diagonals of eliminated rows
6049 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6050 -  b - optional vector of right hand side, that will be adjusted by provided solution
6051 
6052    Note:
6053    See `MatZeroRows()` for details on how this routine operates.
6054 
6055    Level: intermediate
6056 
6057 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6058           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6059 @*/
6060 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6061   PetscInt        numRows = 0;
6062   const PetscInt *rows    = NULL;
6063 
6064   PetscFunctionBegin;
6065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6066   PetscValidType(mat, 1);
6067   if (is) {
6068     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6069     PetscCall(ISGetLocalSize(is, &numRows));
6070     PetscCall(ISGetIndices(is, &rows));
6071   }
6072   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6073   if (is) PetscCall(ISRestoreIndices(is, &rows));
6074   PetscFunctionReturn(0);
6075 }
6076 
6077 /*@
6078    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6079    of a set of rows of a matrix. These rows must be local to the process.
6080 
6081    Collective on mat
6082 
6083    Input Parameters:
6084 +  mat - the matrix
6085 .  numRows - the number of rows to remove
6086 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6087 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6088 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6089 -  b - optional vector of right hand side, that will be adjusted by provided solution
6090 
6091    Notes:
6092    See `MatZeroRows()` for details on how this routine operates.
6093 
6094    The grid coordinates are across the entire grid, not just the local portion
6095 
6096    In Fortran idxm and idxn should be declared as
6097 $     MatStencil idxm(4,m)
6098    and the values inserted using
6099 $    idxm(MatStencil_i,1) = i
6100 $    idxm(MatStencil_j,1) = j
6101 $    idxm(MatStencil_k,1) = k
6102 $    idxm(MatStencil_c,1) = c
6103    etc
6104 
6105    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6106    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6107    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6108    `DM_BOUNDARY_PERIODIC` boundary type.
6109 
6110    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
6111    a single value per point) you can skip filling those indices.
6112 
6113    Level: intermediate
6114 
6115 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6116           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6117 @*/
6118 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) {
6119   PetscInt  dim    = mat->stencil.dim;
6120   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6121   PetscInt *dims   = mat->stencil.dims + 1;
6122   PetscInt *starts = mat->stencil.starts;
6123   PetscInt *dxm    = (PetscInt *)rows;
6124   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6125 
6126   PetscFunctionBegin;
6127   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6128   PetscValidType(mat, 1);
6129   if (numRows) PetscValidPointer(rows, 3);
6130 
6131   PetscCall(PetscMalloc1(numRows, &jdxm));
6132   for (i = 0; i < numRows; ++i) {
6133     /* Skip unused dimensions (they are ordered k, j, i, c) */
6134     for (j = 0; j < 3 - sdim; ++j) dxm++;
6135     /* Local index in X dir */
6136     tmp = *dxm++ - starts[0];
6137     /* Loop over remaining dimensions */
6138     for (j = 0; j < dim - 1; ++j) {
6139       /* If nonlocal, set index to be negative */
6140       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6141       /* Update local index */
6142       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6143     }
6144     /* Skip component slot if necessary */
6145     if (mat->stencil.noc) dxm++;
6146     /* Local row number */
6147     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6148   }
6149   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6150   PetscCall(PetscFree(jdxm));
6151   PetscFunctionReturn(0);
6152 }
6153 
6154 /*@
6155    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6156    of a set of rows and columns of a matrix.
6157 
6158    Collective on mat
6159 
6160    Input Parameters:
6161 +  mat - the matrix
6162 .  numRows - the number of rows/columns to remove
6163 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6164 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6165 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6166 -  b - optional vector of right hand side, that will be adjusted by provided solution
6167 
6168    Notes:
6169    See `MatZeroRowsColumns()` for details on how this routine operates.
6170 
6171    The grid coordinates are across the entire grid, not just the local portion
6172 
6173    In Fortran idxm and idxn should be declared as
6174 $     MatStencil idxm(4,m)
6175    and the values inserted using
6176 $    idxm(MatStencil_i,1) = i
6177 $    idxm(MatStencil_j,1) = j
6178 $    idxm(MatStencil_k,1) = k
6179 $    idxm(MatStencil_c,1) = c
6180    etc
6181 
6182    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6183    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6184    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6185    `DM_BOUNDARY_PERIODIC` boundary type.
6186 
6187    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
6188    a single value per point) you can skip filling those indices.
6189 
6190    Level: intermediate
6191 
6192 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6193           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6194 @*/
6195 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) {
6196   PetscInt  dim    = mat->stencil.dim;
6197   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6198   PetscInt *dims   = mat->stencil.dims + 1;
6199   PetscInt *starts = mat->stencil.starts;
6200   PetscInt *dxm    = (PetscInt *)rows;
6201   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6202 
6203   PetscFunctionBegin;
6204   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6205   PetscValidType(mat, 1);
6206   if (numRows) PetscValidPointer(rows, 3);
6207 
6208   PetscCall(PetscMalloc1(numRows, &jdxm));
6209   for (i = 0; i < numRows; ++i) {
6210     /* Skip unused dimensions (they are ordered k, j, i, c) */
6211     for (j = 0; j < 3 - sdim; ++j) dxm++;
6212     /* Local index in X dir */
6213     tmp = *dxm++ - starts[0];
6214     /* Loop over remaining dimensions */
6215     for (j = 0; j < dim - 1; ++j) {
6216       /* If nonlocal, set index to be negative */
6217       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6218       /* Update local index */
6219       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6220     }
6221     /* Skip component slot if necessary */
6222     if (mat->stencil.noc) dxm++;
6223     /* Local row number */
6224     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6225   }
6226   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6227   PetscCall(PetscFree(jdxm));
6228   PetscFunctionReturn(0);
6229 }
6230 
6231 /*@C
6232    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6233    of a set of rows of a matrix; using local numbering of rows.
6234 
6235    Collective on mat
6236 
6237    Input Parameters:
6238 +  mat - the matrix
6239 .  numRows - the number of rows to remove
6240 .  rows - the local row indices
6241 .  diag - value put in all diagonals of eliminated rows
6242 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6243 -  b - optional vector of right hand side, that will be adjusted by provided solution
6244 
6245    Notes:
6246    Before calling `MatZeroRowsLocal()`, the user must first set the
6247    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6248 
6249    See `MatZeroRows()` for details on how this routine operates.
6250 
6251    Level: intermediate
6252 
6253 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6254           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6255 @*/
6256 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6257   PetscFunctionBegin;
6258   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6259   PetscValidType(mat, 1);
6260   if (numRows) PetscValidIntPointer(rows, 3);
6261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6262   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6263   MatCheckPreallocated(mat, 1);
6264 
6265   if (mat->ops->zerorowslocal) {
6266     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6267   } else {
6268     IS              is, newis;
6269     const PetscInt *newRows;
6270 
6271     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6272     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6273     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6274     PetscCall(ISGetIndices(newis, &newRows));
6275     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6276     PetscCall(ISRestoreIndices(newis, &newRows));
6277     PetscCall(ISDestroy(&newis));
6278     PetscCall(ISDestroy(&is));
6279   }
6280   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6281   PetscFunctionReturn(0);
6282 }
6283 
6284 /*@
6285    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6286    of a set of rows of a matrix; using local numbering of rows.
6287 
6288    Collective on mat
6289 
6290    Input Parameters:
6291 +  mat - the matrix
6292 .  is - index set of rows to remove
6293 .  diag - value put in all diagonals of eliminated rows
6294 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6295 -  b - optional vector of right hand side, that will be adjusted by provided solution
6296 
6297    Notes:
6298    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6299    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6300 
6301    See `MatZeroRows()` for details on how this routine operates.
6302 
6303    Level: intermediate
6304 
6305 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6306           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6307 @*/
6308 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6309   PetscInt        numRows;
6310   const PetscInt *rows;
6311 
6312   PetscFunctionBegin;
6313   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6314   PetscValidType(mat, 1);
6315   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6316   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6317   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6318   MatCheckPreallocated(mat, 1);
6319 
6320   PetscCall(ISGetLocalSize(is, &numRows));
6321   PetscCall(ISGetIndices(is, &rows));
6322   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6323   PetscCall(ISRestoreIndices(is, &rows));
6324   PetscFunctionReturn(0);
6325 }
6326 
6327 /*@
6328    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6329    of a set of rows and columns of a matrix; using local numbering of rows.
6330 
6331    Collective on mat
6332 
6333    Input Parameters:
6334 +  mat - the matrix
6335 .  numRows - the number of rows to remove
6336 .  rows - the global row indices
6337 .  diag - value put in all diagonals of eliminated rows
6338 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6339 -  b - optional vector of right hand side, that will be adjusted by provided solution
6340 
6341    Notes:
6342    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6343    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6344 
6345    See `MatZeroRowsColumns()` for details on how this routine operates.
6346 
6347    Level: intermediate
6348 
6349 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6350           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6351 @*/
6352 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6353   IS              is, newis;
6354   const PetscInt *newRows;
6355 
6356   PetscFunctionBegin;
6357   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6358   PetscValidType(mat, 1);
6359   if (numRows) PetscValidIntPointer(rows, 3);
6360   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6361   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6362   MatCheckPreallocated(mat, 1);
6363 
6364   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6365   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6366   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6367   PetscCall(ISGetIndices(newis, &newRows));
6368   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6369   PetscCall(ISRestoreIndices(newis, &newRows));
6370   PetscCall(ISDestroy(&newis));
6371   PetscCall(ISDestroy(&is));
6372   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6373   PetscFunctionReturn(0);
6374 }
6375 
6376 /*@
6377    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6378    of a set of rows and columns of a matrix; using local numbering of rows.
6379 
6380    Collective on Mat
6381 
6382    Input Parameters:
6383 +  mat - the matrix
6384 .  is - index set of rows to remove
6385 .  diag - value put in all diagonals of eliminated rows
6386 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6387 -  b - optional vector of right hand side, that will be adjusted by provided solution
6388 
6389    Notes:
6390    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6391    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6392 
6393    See `MatZeroRowsColumns()` for details on how this routine operates.
6394 
6395    Level: intermediate
6396 
6397 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6398           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6399 @*/
6400 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6401   PetscInt        numRows;
6402   const PetscInt *rows;
6403 
6404   PetscFunctionBegin;
6405   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6406   PetscValidType(mat, 1);
6407   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6408   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6409   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6410   MatCheckPreallocated(mat, 1);
6411 
6412   PetscCall(ISGetLocalSize(is, &numRows));
6413   PetscCall(ISGetIndices(is, &rows));
6414   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6415   PetscCall(ISRestoreIndices(is, &rows));
6416   PetscFunctionReturn(0);
6417 }
6418 
6419 /*@C
6420    MatGetSize - Returns the numbers of rows and columns in a matrix.
6421 
6422    Not Collective
6423 
6424    Input Parameter:
6425 .  mat - the matrix
6426 
6427    Output Parameters:
6428 +  m - the number of global rows
6429 -  n - the number of global columns
6430 
6431    Note: both output parameters can be NULL on input.
6432 
6433    Level: beginner
6434 
6435 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6436 @*/
6437 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) {
6438   PetscFunctionBegin;
6439   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6440   if (m) *m = mat->rmap->N;
6441   if (n) *n = mat->cmap->N;
6442   PetscFunctionReturn(0);
6443 }
6444 
6445 /*@C
6446    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6447    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6448 
6449    Not Collective
6450 
6451    Input Parameter:
6452 .  mat - the matrix
6453 
6454    Output Parameters:
6455 +  m - the number of local rows, use `NULL` to not obtain this value
6456 -  n - the number of local columns, use `NULL` to not obtain this value
6457 
6458    Level: beginner
6459 
6460 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6461 @*/
6462 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) {
6463   PetscFunctionBegin;
6464   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6465   if (m) PetscValidIntPointer(m, 2);
6466   if (n) PetscValidIntPointer(n, 3);
6467   if (m) *m = mat->rmap->n;
6468   if (n) *n = mat->cmap->n;
6469   PetscFunctionReturn(0);
6470 }
6471 
6472 /*@C
6473    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6474    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6475 
6476    Not Collective, unless matrix has not been allocated, then collective on mat
6477 
6478    Input Parameter:
6479 .  mat - the matrix
6480 
6481    Output Parameters:
6482 +  m - the global index of the first local column, use `NULL` to not obtain this value
6483 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6484 
6485    Level: developer
6486 
6487 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6488 @*/
6489 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) {
6490   PetscFunctionBegin;
6491   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6492   PetscValidType(mat, 1);
6493   if (m) PetscValidIntPointer(m, 2);
6494   if (n) PetscValidIntPointer(n, 3);
6495   MatCheckPreallocated(mat, 1);
6496   if (m) *m = mat->cmap->rstart;
6497   if (n) *n = mat->cmap->rend;
6498   PetscFunctionReturn(0);
6499 }
6500 
6501 /*@C
6502    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6503    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
6504    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6505 
6506    Not Collective
6507 
6508    Input Parameter:
6509 .  mat - the matrix
6510 
6511    Output Parameters:
6512 +  m - the global index of the first local row, use `NULL` to not obtain this value
6513 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6514 
6515    Note:
6516   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6517   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6518   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6519 
6520    Level: beginner
6521 
6522 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6523           `PetscLayout`
6524 @*/
6525 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) {
6526   PetscFunctionBegin;
6527   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6528   PetscValidType(mat, 1);
6529   if (m) PetscValidIntPointer(m, 2);
6530   if (n) PetscValidIntPointer(n, 3);
6531   MatCheckPreallocated(mat, 1);
6532   if (m) *m = mat->rmap->rstart;
6533   if (n) *n = mat->rmap->rend;
6534   PetscFunctionReturn(0);
6535 }
6536 
6537 /*@C
6538    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6539    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
6540    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6541 
6542    Not Collective, unless matrix has not been allocated, then collective on mat
6543 
6544    Input Parameters:
6545 .  mat - the matrix
6546 
6547    Output Parameters:
6548 .  ranges - start of each processors portion plus one more than the total length at the end
6549 
6550    Level: beginner
6551 
6552 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6553 @*/
6554 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) {
6555   PetscFunctionBegin;
6556   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6557   PetscValidType(mat, 1);
6558   MatCheckPreallocated(mat, 1);
6559   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6560   PetscFunctionReturn(0);
6561 }
6562 
6563 /*@C
6564    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6565    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6566 
6567    Not Collective, unless matrix has not been allocated, then collective on Mat
6568 
6569    Input Parameters:
6570 .  mat - the matrix
6571 
6572    Output Parameters:
6573 .  ranges - start of each processors portion plus one more then the total length at the end
6574 
6575    Level: beginner
6576 
6577 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6578 @*/
6579 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) {
6580   PetscFunctionBegin;
6581   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6582   PetscValidType(mat, 1);
6583   MatCheckPreallocated(mat, 1);
6584   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6585   PetscFunctionReturn(0);
6586 }
6587 
6588 /*@C
6589    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6590    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6591    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6592 
6593    Not Collective
6594 
6595    Input Parameter:
6596 .  A - matrix
6597 
6598    Output Parameters:
6599 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6600 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6601 
6602    Level: intermediate
6603 
6604 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6605 @*/
6606 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) {
6607   PetscErrorCode (*f)(Mat, IS *, IS *);
6608 
6609   PetscFunctionBegin;
6610   MatCheckPreallocated(A, 1);
6611   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6612   if (f) {
6613     PetscCall((*f)(A, rows, cols));
6614   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6615     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6616     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6617   }
6618   PetscFunctionReturn(0);
6619 }
6620 
6621 /*@C
6622    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6623    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6624    to complete the factorization.
6625 
6626    Collective on fact
6627 
6628    Input Parameters:
6629 +  fact - the factorized matrix obtained with `MatGetFactor()`
6630 .  mat - the matrix
6631 .  row - row permutation
6632 .  column - column permutation
6633 -  info - structure containing
6634 $      levels - number of levels of fill.
6635 $      expected fill - as ratio of original fill.
6636 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6637                 missing diagonal entries)
6638 
6639    Output Parameters:
6640 .  fact - new matrix that has been symbolically factored
6641 
6642    Level: developer
6643 
6644    Notes:
6645    See Users-Manual: ch_mat for additional information about choosing the fill factor for better efficiency.
6646 
6647    Most users should employ the `KSP` interface for linear solvers
6648    instead of working directly with matrix algebra routines such as this.
6649    See, e.g., `KSPCreate()`.
6650 
6651    Uses the definition of level of fill as in Y. Saad, 2003
6652 
6653    Developer Note:
6654    The Fortran interface is not autogenerated as the f90
6655    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6656 
6657    References:
6658 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6659 
6660 .seealso: `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6661           `MatGetOrdering()`, `MatFactorInfo`
6662 @*/
6663 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) {
6664   PetscFunctionBegin;
6665   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6666   PetscValidType(mat, 2);
6667   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6668   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6669   PetscValidPointer(info, 5);
6670   PetscValidPointer(fact, 1);
6671   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6672   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6673   if (!fact->ops->ilufactorsymbolic) {
6674     MatSolverType stype;
6675     PetscCall(MatFactorGetSolverType(fact, &stype));
6676     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6677   }
6678   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6679   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6680   MatCheckPreallocated(mat, 2);
6681 
6682   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6683   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6684   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6685   PetscFunctionReturn(0);
6686 }
6687 
6688 /*@C
6689    MatICCFactorSymbolic - Performs symbolic incomplete
6690    Cholesky factorization for a symmetric matrix.  Use
6691    `MatCholeskyFactorNumeric()` to complete the factorization.
6692 
6693    Collective on fact
6694 
6695    Input Parameters:
6696 +  fact - the factorized matrix obtained with `MatGetFactor()`
6697 .  mat - the matrix to be factored
6698 .  perm - row and column permutation
6699 -  info - structure containing
6700 $      levels - number of levels of fill.
6701 $      expected fill - as ratio of original fill.
6702 
6703    Output Parameter:
6704 .  fact - the factored matrix
6705 
6706    Level: developer
6707 
6708    Notes:
6709    Most users should employ the `KSP` interface for linear solvers
6710    instead of working directly with matrix algebra routines such as this.
6711    See, e.g., `KSPCreate()`.
6712 
6713    This uses the definition of level of fill as in Y. Saad, 2003
6714 
6715    Developer Note:
6716    The Fortran interface is not autogenerated as the f90
6717    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6718 
6719    References:
6720 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6721 
6722 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6723 @*/
6724 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) {
6725   PetscFunctionBegin;
6726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6727   PetscValidType(mat, 2);
6728   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6729   PetscValidPointer(info, 4);
6730   PetscValidPointer(fact, 1);
6731   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6732   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6733   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6734   if (!(fact)->ops->iccfactorsymbolic) {
6735     MatSolverType stype;
6736     PetscCall(MatFactorGetSolverType(fact, &stype));
6737     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6738   }
6739   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6740   MatCheckPreallocated(mat, 2);
6741 
6742   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6743   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6744   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6745   PetscFunctionReturn(0);
6746 }
6747 
6748 /*@C
6749    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6750    points to an array of valid matrices, they may be reused to store the new
6751    submatrices.
6752 
6753    Collective on mat
6754 
6755    Input Parameters:
6756 +  mat - the matrix
6757 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6758 .  irow, icol - index sets of rows and columns to extract
6759 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6760 
6761    Output Parameter:
6762 .  submat - the array of submatrices
6763 
6764    Notes:
6765    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6766    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6767    to extract a parallel submatrix.
6768 
6769    Some matrix types place restrictions on the row and column
6770    indices, such as that they be sorted or that they be equal to each other.
6771 
6772    The index sets may not have duplicate entries.
6773 
6774    When extracting submatrices from a parallel matrix, each processor can
6775    form a different submatrix by setting the rows and columns of its
6776    individual index sets according to the local submatrix desired.
6777 
6778    When finished using the submatrices, the user should destroy
6779    them with `MatDestroySubMatrices()`.
6780 
6781    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6782    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6783 
6784    This routine creates the matrices in submat; you should NOT create them before
6785    calling it. It also allocates the array of matrix pointers submat.
6786 
6787    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6788    request one row/column in a block, they must request all rows/columns that are in
6789    that block. For example, if the block size is 2 you cannot request just row 0 and
6790    column 0.
6791 
6792    Fortran Note:
6793    The Fortran interface is slightly different from that given below; it
6794    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.
6795 
6796    Level: advanced
6797 
6798 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6799 @*/
6800 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) {
6801   PetscInt  i;
6802   PetscBool eq;
6803 
6804   PetscFunctionBegin;
6805   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6806   PetscValidType(mat, 1);
6807   if (n) {
6808     PetscValidPointer(irow, 3);
6809     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
6810     PetscValidPointer(icol, 4);
6811     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
6812   }
6813   PetscValidPointer(submat, 6);
6814   if (n && scall == MAT_REUSE_MATRIX) {
6815     PetscValidPointer(*submat, 6);
6816     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
6817   }
6818   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6819   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6820   MatCheckPreallocated(mat, 1);
6821   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
6822   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6823   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
6824   for (i = 0; i < n; i++) {
6825     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6826     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
6827     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
6828 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6829     if (mat->boundtocpu && mat->bindingpropagates) {
6830       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
6831       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
6832     }
6833 #endif
6834   }
6835   PetscFunctionReturn(0);
6836 }
6837 
6838 /*@C
6839    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
6840 
6841    Collective on mat
6842 
6843    Input Parameters:
6844 +  mat - the matrix
6845 .  n   - the number of submatrixes to be extracted
6846 .  irow, icol - index sets of rows and columns to extract
6847 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6848 
6849    Output Parameter:
6850 .  submat - the array of submatrices
6851 
6852    Level: advanced
6853 
6854    Note:
6855    This is used by `PCGASM`
6856 
6857 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6858 @*/
6859 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) {
6860   PetscInt  i;
6861   PetscBool eq;
6862 
6863   PetscFunctionBegin;
6864   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6865   PetscValidType(mat, 1);
6866   if (n) {
6867     PetscValidPointer(irow, 3);
6868     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
6869     PetscValidPointer(icol, 4);
6870     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
6871   }
6872   PetscValidPointer(submat, 6);
6873   if (n && scall == MAT_REUSE_MATRIX) {
6874     PetscValidPointer(*submat, 6);
6875     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
6876   }
6877   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6878   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6879   MatCheckPreallocated(mat, 1);
6880 
6881   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
6882   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6883   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
6884   for (i = 0; i < n; i++) {
6885     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
6886     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
6887   }
6888   PetscFunctionReturn(0);
6889 }
6890 
6891 /*@C
6892    MatDestroyMatrices - Destroys an array of matrices.
6893 
6894    Collective on mat
6895 
6896    Input Parameters:
6897 +  n - the number of local matrices
6898 -  mat - the matrices (note that this is a pointer to the array of matrices)
6899 
6900    Level: advanced
6901 
6902     Note:
6903     Frees not only the matrices, but also the array that contains the matrices
6904            In Fortran will not free the array.
6905 
6906 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6907 @*/
6908 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) {
6909   PetscInt i;
6910 
6911   PetscFunctionBegin;
6912   if (!*mat) PetscFunctionReturn(0);
6913   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
6914   PetscValidPointer(mat, 2);
6915 
6916   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
6917 
6918   /* memory is allocated even if n = 0 */
6919   PetscCall(PetscFree(*mat));
6920   PetscFunctionReturn(0);
6921 }
6922 
6923 /*@C
6924    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
6925 
6926    Collective on mat
6927 
6928    Input Parameters:
6929 +  n - the number of local matrices
6930 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6931                        sequence of MatCreateSubMatrices())
6932 
6933    Level: advanced
6934 
6935     Note:
6936     Frees not only the matrices, but also the array that contains the matrices
6937            In Fortran will not free the array.
6938 
6939 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6940 @*/
6941 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) {
6942   Mat mat0;
6943 
6944   PetscFunctionBegin;
6945   if (!*mat) PetscFunctionReturn(0);
6946   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
6947   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
6948   PetscValidPointer(mat, 2);
6949 
6950   mat0 = (*mat)[0];
6951   if (mat0 && mat0->ops->destroysubmatrices) {
6952     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
6953   } else {
6954     PetscCall(MatDestroyMatrices(n, mat));
6955   }
6956   PetscFunctionReturn(0);
6957 }
6958 
6959 /*@C
6960    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
6961 
6962    Collective on mat
6963 
6964    Input Parameters:
6965 .  mat - the matrix
6966 
6967    Output Parameter:
6968 .  matstruct - the sequential matrix with the nonzero structure of mat
6969 
6970   Level: developer
6971 
6972 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6973 @*/
6974 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) {
6975   PetscFunctionBegin;
6976   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6977   PetscValidPointer(matstruct, 2);
6978 
6979   PetscValidType(mat, 1);
6980   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6981   MatCheckPreallocated(mat, 1);
6982 
6983   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
6984   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
6985   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
6986   PetscFunctionReturn(0);
6987 }
6988 
6989 /*@C
6990    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
6991 
6992    Collective on mat
6993 
6994    Input Parameters:
6995 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
6996                        sequence of `MatGetSequentialNonzeroStructure()`)
6997 
6998    Level: advanced
6999 
7000     Note:
7001     Frees not only the matrices, but also the array that contains the matrices
7002 
7003 .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7004 @*/
7005 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) {
7006   PetscFunctionBegin;
7007   PetscValidPointer(mat, 1);
7008   PetscCall(MatDestroy(mat));
7009   PetscFunctionReturn(0);
7010 }
7011 
7012 /*@
7013    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7014    replaces the index sets by larger ones that represent submatrices with
7015    additional overlap.
7016 
7017    Collective on mat
7018 
7019    Input Parameters:
7020 +  mat - the matrix
7021 .  n   - the number of index sets
7022 .  is  - the array of index sets (these index sets will changed during the call)
7023 -  ov  - the additional overlap requested
7024 
7025    Options Database:
7026 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7027 
7028    Level: developer
7029 
7030    Developer Note:
7031    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.
7032 
7033 .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7034 @*/
7035 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) {
7036   PetscInt i, bs, cbs;
7037 
7038   PetscFunctionBegin;
7039   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7040   PetscValidType(mat, 1);
7041   PetscValidLogicalCollectiveInt(mat, n, 2);
7042   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7043   if (n) {
7044     PetscValidPointer(is, 3);
7045     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7046   }
7047   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7048   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7049   MatCheckPreallocated(mat, 1);
7050 
7051   if (!ov || !n) PetscFunctionReturn(0);
7052   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7053   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7054   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7055   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7056   if (bs == cbs) {
7057     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7058   }
7059   PetscFunctionReturn(0);
7060 }
7061 
7062 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7063 
7064 /*@
7065    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7066    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7067    additional overlap.
7068 
7069    Collective on mat
7070 
7071    Input Parameters:
7072 +  mat - the matrix
7073 .  n   - the number of index sets
7074 .  is  - the array of index sets (these index sets will changed during the call)
7075 -  ov  - the additional overlap requested
7076 
7077 `   Options Database:
7078 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7079 
7080    Level: developer
7081 
7082 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7083 @*/
7084 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) {
7085   PetscInt i;
7086 
7087   PetscFunctionBegin;
7088   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7089   PetscValidType(mat, 1);
7090   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7091   if (n) {
7092     PetscValidPointer(is, 3);
7093     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7094   }
7095   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7096   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7097   MatCheckPreallocated(mat, 1);
7098   if (!ov) PetscFunctionReturn(0);
7099   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7100   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7101   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7102   PetscFunctionReturn(0);
7103 }
7104 
7105 /*@
7106    MatGetBlockSize - Returns the matrix block size.
7107 
7108    Not Collective
7109 
7110    Input Parameter:
7111 .  mat - the matrix
7112 
7113    Output Parameter:
7114 .  bs - block size
7115 
7116    Notes:
7117     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7118 
7119    If the block size has not been set yet this routine returns 1.
7120 
7121    Level: intermediate
7122 
7123 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7124 @*/
7125 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) {
7126   PetscFunctionBegin;
7127   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7128   PetscValidIntPointer(bs, 2);
7129   *bs = PetscAbs(mat->rmap->bs);
7130   PetscFunctionReturn(0);
7131 }
7132 
7133 /*@
7134    MatGetBlockSizes - Returns the matrix block row and column sizes.
7135 
7136    Not Collective
7137 
7138    Input Parameter:
7139 .  mat - the matrix
7140 
7141    Output Parameters:
7142 +  rbs - row block size
7143 -  cbs - column block size
7144 
7145    Notes:
7146     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7147     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7148 
7149    If a block size has not been set yet this routine returns 1.
7150 
7151    Level: intermediate
7152 
7153 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7154 @*/
7155 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) {
7156   PetscFunctionBegin;
7157   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7158   if (rbs) PetscValidIntPointer(rbs, 2);
7159   if (cbs) PetscValidIntPointer(cbs, 3);
7160   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7161   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7162   PetscFunctionReturn(0);
7163 }
7164 
7165 /*@
7166    MatSetBlockSize - Sets the matrix block size.
7167 
7168    Logically Collective on mat
7169 
7170    Input Parameters:
7171 +  mat - the matrix
7172 -  bs - block size
7173 
7174    Notes:
7175     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7176     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7177 
7178     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7179     is compatible with the matrix local sizes.
7180 
7181    Level: intermediate
7182 
7183 .seealso:  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7184 @*/
7185 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) {
7186   PetscFunctionBegin;
7187   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7188   PetscValidLogicalCollectiveInt(mat, bs, 2);
7189   PetscCall(MatSetBlockSizes(mat, bs, bs));
7190   PetscFunctionReturn(0);
7191 }
7192 
7193 typedef struct {
7194   PetscInt         n;
7195   IS              *is;
7196   Mat             *mat;
7197   PetscObjectState nonzerostate;
7198   Mat              C;
7199 } EnvelopeData;
7200 
7201 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) {
7202   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7203   PetscCall(PetscFree(edata->is));
7204   PetscCall(PetscFree(edata));
7205   return 0;
7206 }
7207 
7208 /*
7209    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7210          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7211 
7212    Collective on mat
7213 
7214    Input Parameter:
7215 .  mat - the matrix
7216 
7217    Notes:
7218      There can be zeros within the blocks
7219 
7220      The blocks can overlap between processes, including laying on more than two processes
7221 
7222 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7223 */
7224 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) {
7225   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7226   PetscInt          *diag, *odiag, sc;
7227   VecScatter         scatter;
7228   PetscScalar       *seqv;
7229   const PetscScalar *parv;
7230   const PetscInt    *ia, *ja;
7231   PetscBool          set, flag, done;
7232   Mat                AA = mat, A;
7233   MPI_Comm           comm;
7234   PetscMPIInt        rank, size, tag;
7235   MPI_Status         status;
7236   PetscContainer     container;
7237   EnvelopeData      *edata;
7238   Vec                seq, par;
7239   IS                 isglobal;
7240 
7241   PetscFunctionBegin;
7242   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7243   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7244   if (!set || !flag) {
7245     /* TOO: only needs nonzero structure of transpose */
7246     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7247     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7248   }
7249   PetscCall(MatAIJGetLocalMat(AA, &A));
7250   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7251   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7252 
7253   PetscCall(MatGetLocalSize(mat, &n, NULL));
7254   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7255   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7256   PetscCallMPI(MPI_Comm_size(comm, &size));
7257   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7258 
7259   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7260 
7261   if (rank > 0) {
7262     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7263     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7264   }
7265   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7266   for (i = 0; i < n; i++) {
7267     env = PetscMax(env, ja[ia[i + 1] - 1]);
7268     II  = rstart + i;
7269     if (env == II) {
7270       starts[lblocks]  = tbs;
7271       sizes[lblocks++] = 1 + II - tbs;
7272       tbs              = 1 + II;
7273     }
7274   }
7275   if (rank < size - 1) {
7276     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7277     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7278   }
7279 
7280   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7281   if (!set || !flag) PetscCall(MatDestroy(&AA));
7282   PetscCall(MatDestroy(&A));
7283 
7284   PetscCall(PetscNew(&edata));
7285   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7286   edata->n = lblocks;
7287   /* create IS needed for extracting blocks from the original matrix */
7288   PetscCall(PetscMalloc1(lblocks, &edata->is));
7289   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7290 
7291   /* Create the resulting inverse matrix structure with preallocation information */
7292   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7293   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7294   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7295   PetscCall(MatSetType(edata->C, MATAIJ));
7296 
7297   /* Communicate the start and end of each row, from each block to the correct rank */
7298   /* TODO: Use PetscSF instead of VecScatter */
7299   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7300   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7301   PetscCall(VecGetArrayWrite(seq, &seqv));
7302   for (PetscInt i = 0; i < lblocks; i++) {
7303     for (PetscInt j = 0; j < sizes[i]; j++) {
7304       seqv[cnt]     = starts[i];
7305       seqv[cnt + 1] = starts[i] + sizes[i];
7306       cnt += 2;
7307     }
7308   }
7309   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7310   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7311   sc -= cnt;
7312   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7313   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7314   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7315   PetscCall(ISDestroy(&isglobal));
7316   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7317   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7318   PetscCall(VecScatterDestroy(&scatter));
7319   PetscCall(VecDestroy(&seq));
7320   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7321   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7322   PetscCall(VecGetArrayRead(par, &parv));
7323   cnt = 0;
7324   PetscCall(MatGetSize(mat, NULL, &n));
7325   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7326     PetscInt start, end, d = 0, od = 0;
7327 
7328     start = (PetscInt)PetscRealPart(parv[cnt]);
7329     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7330     cnt += 2;
7331 
7332     if (start < cstart) {
7333       od += cstart - start + n - cend;
7334       d += cend - cstart;
7335     } else if (start < cend) {
7336       od += n - cend;
7337       d += cend - start;
7338     } else od += n - start;
7339     if (end <= cstart) {
7340       od -= cstart - end + n - cend;
7341       d -= cend - cstart;
7342     } else if (end < cend) {
7343       od -= n - cend;
7344       d -= cend - end;
7345     } else od -= n - end;
7346 
7347     odiag[i] = od;
7348     diag[i]  = d;
7349   }
7350   PetscCall(VecRestoreArrayRead(par, &parv));
7351   PetscCall(VecDestroy(&par));
7352   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7353   PetscCall(PetscFree2(diag, odiag));
7354   PetscCall(PetscFree2(sizes, starts));
7355 
7356   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7357   PetscCall(PetscContainerSetPointer(container, edata));
7358   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7359   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7360   PetscCall(PetscObjectDereference((PetscObject)container));
7361   PetscFunctionReturn(0);
7362 }
7363 
7364 /*@
7365   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7366 
7367   Collective on A
7368 
7369   Input Parameters:
7370 . A - the matrix
7371 
7372   Output Parameters:
7373 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7374 
7375   Note:
7376      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7377 
7378   Level: advanced
7379 
7380 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7381 @*/
7382 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) {
7383   PetscContainer   container;
7384   EnvelopeData    *edata;
7385   PetscObjectState nonzerostate;
7386 
7387   PetscFunctionBegin;
7388   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7389   if (!container) {
7390     PetscCall(MatComputeVariableBlockEnvelope(A));
7391     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7392   }
7393   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7394   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7395   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7396   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7397 
7398   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7399   *C = edata->C;
7400 
7401   for (PetscInt i = 0; i < edata->n; i++) {
7402     Mat          D;
7403     PetscScalar *dvalues;
7404 
7405     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7406     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7407     PetscCall(MatSeqDenseInvert(D));
7408     PetscCall(MatDenseGetArray(D, &dvalues));
7409     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7410     PetscCall(MatDestroy(&D));
7411   }
7412   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7413   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7414   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7415   PetscFunctionReturn(0);
7416 }
7417 
7418 /*@
7419    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7420 
7421    Logically Collective on mat
7422 
7423    Input Parameters:
7424 +  mat - the matrix
7425 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7426 -  bsizes - the block sizes
7427 
7428    Notes:
7429     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7430 
7431     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.
7432 
7433    Level: intermediate
7434 
7435 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7436           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7437 @*/
7438 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) {
7439   PetscInt i, ncnt = 0, nlocal;
7440 
7441   PetscFunctionBegin;
7442   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7443   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7444   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7445   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7446   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);
7447   PetscCall(PetscFree(mat->bsizes));
7448   mat->nblocks = nblocks;
7449   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7450   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7451   PetscFunctionReturn(0);
7452 }
7453 
7454 /*@C
7455    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7456 
7457    Logically Collective on mat
7458 
7459    Input Parameter:
7460 .  mat - the matrix
7461 
7462    Output Parameters:
7463 +  nblocks - the number of blocks on this process
7464 -  bsizes - the block sizes
7465 
7466    Fortran Note:
7467    Currently not supported from Fortran
7468 
7469    Level: intermediate
7470 
7471 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7472 @*/
7473 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) {
7474   PetscFunctionBegin;
7475   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7476   *nblocks = mat->nblocks;
7477   *bsizes  = mat->bsizes;
7478   PetscFunctionReturn(0);
7479 }
7480 
7481 /*@
7482    MatSetBlockSizes - Sets the matrix block row and column sizes.
7483 
7484    Logically Collective on mat
7485 
7486    Input Parameters:
7487 +  mat - the matrix
7488 .  rbs - row block size
7489 -  cbs - column block size
7490 
7491    Notes:
7492     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7493     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7494     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7495 
7496     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7497     are compatible with the matrix local sizes.
7498 
7499     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7500 
7501    Level: intermediate
7502 
7503 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7504 @*/
7505 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) {
7506   PetscFunctionBegin;
7507   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7508   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7509   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7510   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7511   if (mat->rmap->refcnt) {
7512     ISLocalToGlobalMapping l2g  = NULL;
7513     PetscLayout            nmap = NULL;
7514 
7515     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7516     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7517     PetscCall(PetscLayoutDestroy(&mat->rmap));
7518     mat->rmap          = nmap;
7519     mat->rmap->mapping = l2g;
7520   }
7521   if (mat->cmap->refcnt) {
7522     ISLocalToGlobalMapping l2g  = NULL;
7523     PetscLayout            nmap = NULL;
7524 
7525     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7526     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7527     PetscCall(PetscLayoutDestroy(&mat->cmap));
7528     mat->cmap          = nmap;
7529     mat->cmap->mapping = l2g;
7530   }
7531   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7532   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7533   PetscFunctionReturn(0);
7534 }
7535 
7536 /*@
7537    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7538 
7539    Logically Collective on mat
7540 
7541    Input Parameters:
7542 +  mat - the matrix
7543 .  fromRow - matrix from which to copy row block size
7544 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7545 
7546    Level: developer
7547 
7548 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7549 @*/
7550 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) {
7551   PetscFunctionBegin;
7552   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7553   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7554   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7555   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7556   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7557   PetscFunctionReturn(0);
7558 }
7559 
7560 /*@
7561    MatResidual - Default routine to calculate the residual r = b - Ax
7562 
7563    Collective on mat
7564 
7565    Input Parameters:
7566 +  mat - the matrix
7567 .  b   - the right-hand-side
7568 -  x   - the approximate solution
7569 
7570    Output Parameter:
7571 .  r - location to store the residual
7572 
7573    Level: developer
7574 
7575 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7576 @*/
7577 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) {
7578   PetscFunctionBegin;
7579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7580   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7581   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7582   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7583   PetscValidType(mat, 1);
7584   MatCheckPreallocated(mat, 1);
7585   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7586   if (!mat->ops->residual) {
7587     PetscCall(MatMult(mat, x, r));
7588     PetscCall(VecAYPX(r, -1.0, b));
7589   } else {
7590     PetscUseTypeMethod(mat, residual, b, x, r);
7591   }
7592   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7593   PetscFunctionReturn(0);
7594 }
7595 
7596 /*@C
7597     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7598 
7599    Collective on mat
7600 
7601     Input Parameters:
7602 +   mat - the matrix
7603 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7604 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7605 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7606                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7607                  always used.
7608 
7609     Output Parameters:
7610 +   n - number of local rows in the (possibly compressed) matrix
7611 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7612 .   ja - the column indices
7613 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7614            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7615 
7616     Level: developer
7617 
7618     Notes:
7619     You CANNOT change any of the ia[] or ja[] values.
7620 
7621     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7622 
7623     Fortran Notes:
7624     In Fortran use
7625 $
7626 $      PetscInt ia(1), ja(1)
7627 $      PetscOffset iia, jja
7628 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7629 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7630 
7631      or
7632 $
7633 $    PetscInt, pointer :: ia(:),ja(:)
7634 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7635 $    ! Access the ith and jth entries via ia(i) and ja(j)
7636 
7637 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7638 @*/
7639 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7640   PetscFunctionBegin;
7641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7642   PetscValidType(mat, 1);
7643   if (n) PetscValidIntPointer(n, 5);
7644   if (ia) PetscValidPointer(ia, 6);
7645   if (ja) PetscValidPointer(ja, 7);
7646   if (done) PetscValidBoolPointer(done, 8);
7647   MatCheckPreallocated(mat, 1);
7648   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7649   else {
7650     if (done) *done = PETSC_TRUE;
7651     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7652     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7653     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7654   }
7655   PetscFunctionReturn(0);
7656 }
7657 
7658 /*@C
7659     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7660 
7661     Collective on mat
7662 
7663     Input Parameters:
7664 +   mat - the matrix
7665 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7666 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7667                 symmetrized
7668 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7669                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7670                  always used.
7671 .   n - number of columns in the (possibly compressed) matrix
7672 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7673 -   ja - the row indices
7674 
7675     Output Parameters:
7676 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7677 
7678     Level: developer
7679 
7680 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7681 @*/
7682 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7683   PetscFunctionBegin;
7684   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7685   PetscValidType(mat, 1);
7686   PetscValidIntPointer(n, 5);
7687   if (ia) PetscValidPointer(ia, 6);
7688   if (ja) PetscValidPointer(ja, 7);
7689   PetscValidBoolPointer(done, 8);
7690   MatCheckPreallocated(mat, 1);
7691   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7692   else {
7693     *done = PETSC_TRUE;
7694     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7695   }
7696   PetscFunctionReturn(0);
7697 }
7698 
7699 /*@C
7700     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7701 
7702     Collective on mat
7703 
7704     Input Parameters:
7705 +   mat - the matrix
7706 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7707 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7708 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7709                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7710                  always used.
7711 .   n - size of (possibly compressed) matrix
7712 .   ia - the row pointers
7713 -   ja - the column indices
7714 
7715     Output Parameters:
7716 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7717 
7718     Note:
7719     This routine zeros out n, ia, and ja. This is to prevent accidental
7720     us of the array after it has been restored. If you pass NULL, it will
7721     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7722 
7723     Level: developer
7724 
7725 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7726 @*/
7727 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7728   PetscFunctionBegin;
7729   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7730   PetscValidType(mat, 1);
7731   if (ia) PetscValidPointer(ia, 6);
7732   if (ja) PetscValidPointer(ja, 7);
7733   if (done) PetscValidBoolPointer(done, 8);
7734   MatCheckPreallocated(mat, 1);
7735 
7736   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7737   else {
7738     if (done) *done = PETSC_TRUE;
7739     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7740     if (n) *n = 0;
7741     if (ia) *ia = NULL;
7742     if (ja) *ja = NULL;
7743   }
7744   PetscFunctionReturn(0);
7745 }
7746 
7747 /*@C
7748     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7749 
7750     Collective on Mat
7751 
7752     Input Parameters:
7753 +   mat - the matrix
7754 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7755 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7756 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7757                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7758                  always used.
7759 
7760     Output Parameters:
7761 +   n - size of (possibly compressed) matrix
7762 .   ia - the column pointers
7763 .   ja - the row indices
7764 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7765 
7766     Level: developer
7767 
7768 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7769 @*/
7770 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7771   PetscFunctionBegin;
7772   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7773   PetscValidType(mat, 1);
7774   if (ia) PetscValidPointer(ia, 6);
7775   if (ja) PetscValidPointer(ja, 7);
7776   PetscValidBoolPointer(done, 8);
7777   MatCheckPreallocated(mat, 1);
7778 
7779   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7780   else {
7781     *done = PETSC_TRUE;
7782     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7783     if (n) *n = 0;
7784     if (ia) *ia = NULL;
7785     if (ja) *ja = NULL;
7786   }
7787   PetscFunctionReturn(0);
7788 }
7789 
7790 /*@C
7791     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
7792 
7793     Collective on mat
7794 
7795     Input Parameters:
7796 +   mat - the matrix
7797 .   ncolors - max color value
7798 .   n   - number of entries in colorarray
7799 -   colorarray - array indicating color for each column
7800 
7801     Output Parameters:
7802 .   iscoloring - coloring generated using colorarray information
7803 
7804     Level: developer
7805 
7806 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7807 @*/
7808 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) {
7809   PetscFunctionBegin;
7810   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7811   PetscValidType(mat, 1);
7812   PetscValidIntPointer(colorarray, 4);
7813   PetscValidPointer(iscoloring, 5);
7814   MatCheckPreallocated(mat, 1);
7815 
7816   if (!mat->ops->coloringpatch) {
7817     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
7818   } else {
7819     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7820   }
7821   PetscFunctionReturn(0);
7822 }
7823 
7824 /*@
7825    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7826 
7827    Logically Collective on mat
7828 
7829    Input Parameter:
7830 .  mat - the factored matrix to be reset
7831 
7832    Notes:
7833    This routine should be used only with factored matrices formed by in-place
7834    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7835    format).  This option can save memory, for example, when solving nonlinear
7836    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7837    ILU(0) preconditioner.
7838 
7839    Note that one can specify in-place ILU(0) factorization by calling
7840 .vb
7841      PCType(pc,PCILU);
7842      PCFactorSeUseInPlace(pc);
7843 .ve
7844    or by using the options -pc_type ilu -pc_factor_in_place
7845 
7846    In-place factorization ILU(0) can also be used as a local
7847    solver for the blocks within the block Jacobi or additive Schwarz
7848    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7849    for details on setting local solver options.
7850 
7851    Most users should employ the `KSP` interface for linear solvers
7852    instead of working directly with matrix algebra routines such as this.
7853    See, e.g., `KSPCreate()`.
7854 
7855    Level: developer
7856 
7857 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7858 @*/
7859 PetscErrorCode MatSetUnfactored(Mat mat) {
7860   PetscFunctionBegin;
7861   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7862   PetscValidType(mat, 1);
7863   MatCheckPreallocated(mat, 1);
7864   mat->factortype = MAT_FACTOR_NONE;
7865   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
7866   PetscUseTypeMethod(mat, setunfactored);
7867   PetscFunctionReturn(0);
7868 }
7869 
7870 /*MC
7871     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
7872 
7873     Synopsis:
7874     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7875 
7876     Not collective
7877 
7878     Input Parameter:
7879 .   x - matrix
7880 
7881     Output Parameters:
7882 +   xx_v - the Fortran pointer to the array
7883 -   ierr - error code
7884 
7885     Example of Usage:
7886 .vb
7887       PetscScalar, pointer xx_v(:,:)
7888       ....
7889       call MatDenseGetArrayF90(x,xx_v,ierr)
7890       a = xx_v(3)
7891       call MatDenseRestoreArrayF90(x,xx_v,ierr)
7892 .ve
7893 
7894     Level: advanced
7895 
7896 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
7897 
7898 M*/
7899 
7900 /*MC
7901     MatDenseRestoreArrayF90 - Restores a matrix array that has been
7902     accessed with `MatDenseGetArrayF90()`.
7903 
7904     Synopsis:
7905     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7906 
7907     Not collective
7908 
7909     Input Parameters:
7910 +   x - matrix
7911 -   xx_v - the Fortran90 pointer to the array
7912 
7913     Output Parameter:
7914 .   ierr - error code
7915 
7916     Example of Usage:
7917 .vb
7918        PetscScalar, pointer xx_v(:,:)
7919        ....
7920        call MatDenseGetArrayF90(x,xx_v,ierr)
7921        a = xx_v(3)
7922        call MatDenseRestoreArrayF90(x,xx_v,ierr)
7923 .ve
7924 
7925     Level: advanced
7926 
7927 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
7928 
7929 M*/
7930 
7931 /*MC
7932     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
7933 
7934     Synopsis:
7935     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7936 
7937     Not collective
7938 
7939     Input Parameter:
7940 .   x - matrix
7941 
7942     Output Parameters:
7943 +   xx_v - the Fortran pointer to the array
7944 -   ierr - error code
7945 
7946     Example of Usage:
7947 .vb
7948       PetscScalar, pointer xx_v(:)
7949       ....
7950       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7951       a = xx_v(3)
7952       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7953 .ve
7954 
7955     Level: advanced
7956 
7957 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
7958 
7959 M*/
7960 
7961 /*MC
7962     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
7963     accessed with `MatSeqAIJGetArrayF90()`.
7964 
7965     Synopsis:
7966     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7967 
7968     Not collective
7969 
7970     Input Parameters:
7971 +   x - matrix
7972 -   xx_v - the Fortran90 pointer to the array
7973 
7974     Output Parameter:
7975 .   ierr - error code
7976 
7977     Example of Usage:
7978 .vb
7979        PetscScalar, pointer xx_v(:)
7980        ....
7981        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7982        a = xx_v(3)
7983        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7984 .ve
7985 
7986     Level: advanced
7987 
7988 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
7989 
7990 M*/
7991 
7992 /*@
7993     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
7994                       as the original matrix.
7995 
7996     Collective on mat
7997 
7998     Input Parameters:
7999 +   mat - the original matrix
8000 .   isrow - parallel IS containing the rows this processor should obtain
8001 .   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.
8002 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8003 
8004     Output Parameter:
8005 .   newmat - the new submatrix, of the same type as the old
8006 
8007     Level: advanced
8008 
8009     Notes:
8010     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8011 
8012     Some matrix types place restrictions on the row and column indices, such
8013     as that they be sorted or that they be equal to each other.
8014 
8015     The index sets may not have duplicate entries.
8016 
8017       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8018    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8019    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8020    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8021    you are finished using it.
8022 
8023     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8024     the input matrix.
8025 
8026     If iscol is NULL then all columns are obtained (not supported in Fortran).
8027 
8028    Example usage:
8029    Consider the following 8x8 matrix with 34 non-zero values, that is
8030    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8031    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8032    as follows:
8033 
8034 .vb
8035             1  2  0  |  0  3  0  |  0  4
8036     Proc0   0  5  6  |  7  0  0  |  8  0
8037             9  0 10  | 11  0  0  | 12  0
8038     -------------------------------------
8039            13  0 14  | 15 16 17  |  0  0
8040     Proc1   0 18  0  | 19 20 21  |  0  0
8041             0  0  0  | 22 23  0  | 24  0
8042     -------------------------------------
8043     Proc2  25 26 27  |  0  0 28  | 29  0
8044            30  0  0  | 31 32 33  |  0 34
8045 .ve
8046 
8047     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8048 
8049 .vb
8050             2  0  |  0  3  0  |  0
8051     Proc0   5  6  |  7  0  0  |  8
8052     -------------------------------
8053     Proc1  18  0  | 19 20 21  |  0
8054     -------------------------------
8055     Proc2  26 27  |  0  0 28  | 29
8056             0  0  | 31 32 33  |  0
8057 .ve
8058 
8059 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8060 @*/
8061 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) {
8062   PetscMPIInt size;
8063   Mat        *local;
8064   IS          iscoltmp;
8065   PetscBool   flg;
8066 
8067   PetscFunctionBegin;
8068   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8069   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8070   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8071   PetscValidPointer(newmat, 5);
8072   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8073   PetscValidType(mat, 1);
8074   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8075   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8076 
8077   MatCheckPreallocated(mat, 1);
8078   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8079 
8080   if (!iscol || isrow == iscol) {
8081     PetscBool   stride;
8082     PetscMPIInt grabentirematrix = 0, grab;
8083     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8084     if (stride) {
8085       PetscInt first, step, n, rstart, rend;
8086       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8087       if (step == 1) {
8088         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8089         if (rstart == first) {
8090           PetscCall(ISGetLocalSize(isrow, &n));
8091           if (n == rend - rstart) grabentirematrix = 1;
8092         }
8093       }
8094     }
8095     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8096     if (grab) {
8097       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8098       if (cll == MAT_INITIAL_MATRIX) {
8099         *newmat = mat;
8100         PetscCall(PetscObjectReference((PetscObject)mat));
8101       }
8102       PetscFunctionReturn(0);
8103     }
8104   }
8105 
8106   if (!iscol) {
8107     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8108   } else {
8109     iscoltmp = iscol;
8110   }
8111 
8112   /* if original matrix is on just one processor then use submatrix generated */
8113   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8114     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8115     goto setproperties;
8116   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8117     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8118     *newmat = *local;
8119     PetscCall(PetscFree(local));
8120     goto setproperties;
8121   } else if (!mat->ops->createsubmatrix) {
8122     /* Create a new matrix type that implements the operation using the full matrix */
8123     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8124     switch (cll) {
8125     case MAT_INITIAL_MATRIX: PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); break;
8126     case MAT_REUSE_MATRIX: PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); break;
8127     default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8128     }
8129     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8130     goto setproperties;
8131   }
8132 
8133   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8134   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8135   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8136 
8137 setproperties:
8138   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8139   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8140   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8141   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8142   PetscFunctionReturn(0);
8143 }
8144 
8145 /*@
8146    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8147 
8148    Not Collective
8149 
8150    Input Parameters:
8151 +  A - the matrix we wish to propagate options from
8152 -  B - the matrix we wish to propagate options to
8153 
8154    Level: beginner
8155 
8156    Note:
8157    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8158 
8159 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8160 @*/
8161 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) {
8162   PetscFunctionBegin;
8163   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8164   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8165   B->symmetry_eternal            = A->symmetry_eternal;
8166   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8167   B->symmetric                   = A->symmetric;
8168   B->structurally_symmetric      = A->structurally_symmetric;
8169   B->spd                         = A->spd;
8170   B->hermitian                   = A->hermitian;
8171   PetscFunctionReturn(0);
8172 }
8173 
8174 /*@
8175    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8176    used during the assembly process to store values that belong to
8177    other processors.
8178 
8179    Not Collective
8180 
8181    Input Parameters:
8182 +  mat   - the matrix
8183 .  size  - the initial size of the stash.
8184 -  bsize - the initial size of the block-stash(if used).
8185 
8186    Options Database Keys:
8187 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8188 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8189 
8190    Level: intermediate
8191 
8192    Notes:
8193      The block-stash is used for values set with `MatSetValuesBlocked()` while
8194      the stash is used for values set with `MatSetValues()`
8195 
8196      Run with the option -info and look for output of the form
8197      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8198      to determine the appropriate value, MM, to use for size and
8199      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8200      to determine the value, BMM to use for bsize
8201 
8202 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8203 @*/
8204 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) {
8205   PetscFunctionBegin;
8206   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8207   PetscValidType(mat, 1);
8208   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8209   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8210   PetscFunctionReturn(0);
8211 }
8212 
8213 /*@
8214    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8215      the matrix
8216 
8217    Neighbor-wise Collective on mat
8218 
8219    Input Parameters:
8220 +  mat   - the matrix
8221 .  x,y - the vectors
8222 -  w - where the result is stored
8223 
8224    Level: intermediate
8225 
8226    Notes:
8227     w may be the same vector as y.
8228 
8229     This allows one to use either the restriction or interpolation (its transpose)
8230     matrix to do the interpolation
8231 
8232 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8233 @*/
8234 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) {
8235   PetscInt M, N, Ny;
8236 
8237   PetscFunctionBegin;
8238   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8239   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8240   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8241   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8242   PetscCall(MatGetSize(A, &M, &N));
8243   PetscCall(VecGetSize(y, &Ny));
8244   if (M == Ny) {
8245     PetscCall(MatMultAdd(A, x, y, w));
8246   } else {
8247     PetscCall(MatMultTransposeAdd(A, x, y, w));
8248   }
8249   PetscFunctionReturn(0);
8250 }
8251 
8252 /*@
8253    MatInterpolate - y = A*x or A'*x depending on the shape of
8254      the matrix
8255 
8256    Neighbor-wise Collective on mat
8257 
8258    Input Parameters:
8259 +  mat   - the matrix
8260 -  x,y - the vectors
8261 
8262    Level: intermediate
8263 
8264    Note:
8265     This allows one to use either the restriction or interpolation (its transpose)
8266     matrix to do the interpolation
8267 
8268 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8269 @*/
8270 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) {
8271   PetscInt M, N, Ny;
8272 
8273   PetscFunctionBegin;
8274   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8275   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8276   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8277   PetscCall(MatGetSize(A, &M, &N));
8278   PetscCall(VecGetSize(y, &Ny));
8279   if (M == Ny) {
8280     PetscCall(MatMult(A, x, y));
8281   } else {
8282     PetscCall(MatMultTranspose(A, x, y));
8283   }
8284   PetscFunctionReturn(0);
8285 }
8286 
8287 /*@
8288    MatRestrict - y = A*x or A'*x
8289 
8290    Neighbor-wise Collective on Mat
8291 
8292    Input Parameters:
8293 +  mat   - the matrix
8294 -  x,y - the vectors
8295 
8296    Level: intermediate
8297 
8298    Note:
8299     This allows one to use either the restriction or interpolation (its transpose)
8300     matrix to do the restriction
8301 
8302 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8303 @*/
8304 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) {
8305   PetscInt M, N, Ny;
8306 
8307   PetscFunctionBegin;
8308   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8309   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8310   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8311   PetscCall(MatGetSize(A, &M, &N));
8312   PetscCall(VecGetSize(y, &Ny));
8313   if (M == Ny) {
8314     PetscCall(MatMult(A, x, y));
8315   } else {
8316     PetscCall(MatMultTranspose(A, x, y));
8317   }
8318   PetscFunctionReturn(0);
8319 }
8320 
8321 /*@
8322    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8323 
8324    Neighbor-wise Collective on Mat
8325 
8326    Input Parameters:
8327 +  mat   - the matrix
8328 -  w, x - the input dense matrices
8329 
8330    Output Parameters:
8331 .  y - the output dense matrix
8332 
8333    Level: intermediate
8334 
8335    Note:
8336     This allows one to use either the restriction or interpolation (its transpose)
8337     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8338     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8339 
8340 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8341 @*/
8342 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) {
8343   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8344   PetscBool trans = PETSC_TRUE;
8345   MatReuse  reuse = MAT_INITIAL_MATRIX;
8346 
8347   PetscFunctionBegin;
8348   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8349   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8350   PetscValidType(x, 2);
8351   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8352   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8353   PetscCall(MatGetSize(A, &M, &N));
8354   PetscCall(MatGetSize(x, &Mx, &Nx));
8355   if (N == Mx) trans = PETSC_FALSE;
8356   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);
8357   Mo = trans ? N : M;
8358   if (*y) {
8359     PetscCall(MatGetSize(*y, &My, &Ny));
8360     if (Mo == My && Nx == Ny) {
8361       reuse = MAT_REUSE_MATRIX;
8362     } else {
8363       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);
8364       PetscCall(MatDestroy(y));
8365     }
8366   }
8367 
8368   if (w && *y == w) { /* this is to minimize changes in PCMG */
8369     PetscBool flg;
8370 
8371     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8372     if (w) {
8373       PetscInt My, Ny, Mw, Nw;
8374 
8375       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8376       PetscCall(MatGetSize(*y, &My, &Ny));
8377       PetscCall(MatGetSize(w, &Mw, &Nw));
8378       if (!flg || My != Mw || Ny != Nw) w = NULL;
8379     }
8380     if (!w) {
8381       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8382       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8383       PetscCall(PetscLogObjectParent((PetscObject)*y, (PetscObject)w));
8384       PetscCall(PetscObjectDereference((PetscObject)w));
8385     } else {
8386       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8387     }
8388   }
8389   if (!trans) {
8390     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8391   } else {
8392     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8393   }
8394   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8395   PetscFunctionReturn(0);
8396 }
8397 
8398 /*@
8399    MatMatInterpolate - Y = A*X or A'*X
8400 
8401    Neighbor-wise Collective on Mat
8402 
8403    Input Parameters:
8404 +  mat   - the matrix
8405 -  x - the input dense matrix
8406 
8407    Output Parameters:
8408 .  y - the output dense matrix
8409 
8410    Level: intermediate
8411 
8412    Note:
8413     This allows one to use either the restriction or interpolation (its transpose)
8414     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8415     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8416 
8417 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8418 @*/
8419 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) {
8420   PetscFunctionBegin;
8421   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8422   PetscFunctionReturn(0);
8423 }
8424 
8425 /*@
8426    MatMatRestrict - Y = A*X or A'*X
8427 
8428    Neighbor-wise Collective on Mat
8429 
8430    Input Parameters:
8431 +  mat   - the matrix
8432 -  x - the input dense matrix
8433 
8434    Output Parameters:
8435 .  y - the output dense matrix
8436 
8437    Level: intermediate
8438 
8439    Note:
8440     This allows one to use either the restriction or interpolation (its transpose)
8441     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8442     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8443 
8444 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8445 @*/
8446 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) {
8447   PetscFunctionBegin;
8448   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8449   PetscFunctionReturn(0);
8450 }
8451 
8452 /*@
8453    MatGetNullSpace - retrieves the null space of a matrix.
8454 
8455    Logically Collective on mat
8456 
8457    Input Parameters:
8458 +  mat - the matrix
8459 -  nullsp - the null space object
8460 
8461    Level: developer
8462 
8463 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8464 @*/
8465 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) {
8466   PetscFunctionBegin;
8467   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8468   PetscValidPointer(nullsp, 2);
8469   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8470   PetscFunctionReturn(0);
8471 }
8472 
8473 /*@
8474    MatSetNullSpace - attaches a null space to a matrix.
8475 
8476    Logically Collective on mat
8477 
8478    Input Parameters:
8479 +  mat - the matrix
8480 -  nullsp - the null space object
8481 
8482    Level: advanced
8483 
8484    Notes:
8485       This null space is used by the `KSP` linear solvers to solve singular systems.
8486 
8487       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
8488 
8489       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
8490       to zero but the linear system will still be solved in a least squares sense.
8491 
8492       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8493    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).
8494    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
8495    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
8496    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).
8497    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8498 
8499     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8500     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8501     routine also automatically calls `MatSetTransposeNullSpace()`.
8502 
8503     The user should call `MatNullSpaceDestroy()`.
8504 
8505 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8506           `KSPSetPCSide()`
8507 @*/
8508 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) {
8509   PetscFunctionBegin;
8510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8511   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8512   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8513   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8514   mat->nullsp = nullsp;
8515   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8516   PetscFunctionReturn(0);
8517 }
8518 
8519 /*@
8520    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8521 
8522    Logically Collective on mat
8523 
8524    Input Parameters:
8525 +  mat - the matrix
8526 -  nullsp - the null space object
8527 
8528    Level: developer
8529 
8530 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8531 @*/
8532 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) {
8533   PetscFunctionBegin;
8534   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8535   PetscValidType(mat, 1);
8536   PetscValidPointer(nullsp, 2);
8537   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8538   PetscFunctionReturn(0);
8539 }
8540 
8541 /*@
8542    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8543 
8544    Logically Collective on mat
8545 
8546    Input Parameters:
8547 +  mat - the matrix
8548 -  nullsp - the null space object
8549 
8550    Level: advanced
8551 
8552    Notes:
8553    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8554 
8555    See `MatSetNullSpace()`
8556 
8557 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8558 @*/
8559 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) {
8560   PetscFunctionBegin;
8561   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8562   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8563   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8564   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8565   mat->transnullsp = nullsp;
8566   PetscFunctionReturn(0);
8567 }
8568 
8569 /*@
8570    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8571         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8572 
8573    Logically Collective on mat
8574 
8575    Input Parameters:
8576 +  mat - the matrix
8577 -  nullsp - the null space object
8578 
8579    Level: advanced
8580 
8581    Notes:
8582    Overwrites any previous near null space that may have been attached
8583 
8584    You can remove the null space by calling this routine with an nullsp of NULL
8585 
8586 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8587 @*/
8588 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) {
8589   PetscFunctionBegin;
8590   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8591   PetscValidType(mat, 1);
8592   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8593   MatCheckPreallocated(mat, 1);
8594   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8595   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8596   mat->nearnullsp = nullsp;
8597   PetscFunctionReturn(0);
8598 }
8599 
8600 /*@
8601    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8602 
8603    Not Collective
8604 
8605    Input Parameter:
8606 .  mat - the matrix
8607 
8608    Output Parameter:
8609 .  nullsp - the null space object, NULL if not set
8610 
8611    Level: advanced
8612 
8613 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8614 @*/
8615 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) {
8616   PetscFunctionBegin;
8617   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8618   PetscValidType(mat, 1);
8619   PetscValidPointer(nullsp, 2);
8620   MatCheckPreallocated(mat, 1);
8621   *nullsp = mat->nearnullsp;
8622   PetscFunctionReturn(0);
8623 }
8624 
8625 /*@C
8626    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8627 
8628    Collective on mat
8629 
8630    Input Parameters:
8631 +  mat - the matrix
8632 .  row - row/column permutation
8633 .  fill - expected fill factor >= 1.0
8634 -  level - level of fill, for ICC(k)
8635 
8636    Notes:
8637    Probably really in-place only when level of fill is zero, otherwise allocates
8638    new space to store factored matrix and deletes previous memory.
8639 
8640    Most users should employ the `KSP` interface for linear solvers
8641    instead of working directly with matrix algebra routines such as this.
8642    See, e.g., `KSPCreate()`.
8643 
8644    Level: developer
8645 
8646    Developer Note:
8647    The Fortran interface is not autogenerated as the f90
8648    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8649 
8650 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8651 @*/
8652 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) {
8653   PetscFunctionBegin;
8654   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8655   PetscValidType(mat, 1);
8656   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8657   PetscValidPointer(info, 3);
8658   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8659   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8660   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8661   MatCheckPreallocated(mat, 1);
8662   PetscUseTypeMethod(mat, iccfactor, row, info);
8663   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8664   PetscFunctionReturn(0);
8665 }
8666 
8667 /*@
8668    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8669          ghosted ones.
8670 
8671    Not Collective
8672 
8673    Input Parameters:
8674 +  mat - the matrix
8675 -  diag - the diagonal values, including ghost ones
8676 
8677    Level: developer
8678 
8679    Notes:
8680     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8681 
8682     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8683 
8684 .seealso: `MatDiagonalScale()`
8685 @*/
8686 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) {
8687   PetscMPIInt size;
8688 
8689   PetscFunctionBegin;
8690   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8691   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8692   PetscValidType(mat, 1);
8693 
8694   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8695   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8696   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8697   if (size == 1) {
8698     PetscInt n, m;
8699     PetscCall(VecGetSize(diag, &n));
8700     PetscCall(MatGetSize(mat, NULL, &m));
8701     if (m == n) {
8702       PetscCall(MatDiagonalScale(mat, NULL, diag));
8703     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8704   } else {
8705     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8706   }
8707   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
8708   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8709   PetscFunctionReturn(0);
8710 }
8711 
8712 /*@
8713    MatGetInertia - Gets the inertia from a factored matrix
8714 
8715    Collective on mat
8716 
8717    Input Parameter:
8718 .  mat - the matrix
8719 
8720    Output Parameters:
8721 +   nneg - number of negative eigenvalues
8722 .   nzero - number of zero eigenvalues
8723 -   npos - number of positive eigenvalues
8724 
8725    Level: advanced
8726 
8727    Note:
8728     Matrix must have been factored by `MatCholeskyFactor()`
8729 
8730 .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8731 @*/
8732 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) {
8733   PetscFunctionBegin;
8734   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8735   PetscValidType(mat, 1);
8736   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8737   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
8738   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8739   PetscFunctionReturn(0);
8740 }
8741 
8742 /* ----------------------------------------------------------------*/
8743 /*@C
8744    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8745 
8746    Neighbor-wise Collective on mat
8747 
8748    Input Parameters:
8749 +  mat - the factored matrix obtained with `MatGetFactor()`
8750 -  b - the right-hand-side vectors
8751 
8752    Output Parameter:
8753 .  x - the result vectors
8754 
8755    Note:
8756    The vectors b and x cannot be the same.  I.e., one cannot
8757    call `MatSolves`(A,x,x).
8758 
8759    Level: developer
8760 
8761 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8762 @*/
8763 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) {
8764   PetscFunctionBegin;
8765   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8766   PetscValidType(mat, 1);
8767   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
8768   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8769   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
8770 
8771   MatCheckPreallocated(mat, 1);
8772   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
8773   PetscUseTypeMethod(mat, solves, b, x);
8774   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
8775   PetscFunctionReturn(0);
8776 }
8777 
8778 /*@
8779    MatIsSymmetric - Test whether a matrix is symmetric
8780 
8781    Collective on mat
8782 
8783    Input Parameters:
8784 +  A - the matrix to test
8785 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8786 
8787    Output Parameters:
8788 .  flg - the result
8789 
8790    Notes:
8791     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8792 
8793     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
8794 
8795     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8796     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8797 
8798    Level: intermediate
8799 
8800 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8801           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8802 @*/
8803 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) {
8804   PetscFunctionBegin;
8805   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8806   PetscValidBoolPointer(flg, 3);
8807 
8808   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8809   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8810   else {
8811     if (!A->ops->issymmetric) {
8812       MatType mattype;
8813       PetscCall(MatGetType(A, &mattype));
8814       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8815     }
8816     PetscUseTypeMethod(A, issymmetric, tol, flg);
8817     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
8818   }
8819   PetscFunctionReturn(0);
8820 }
8821 
8822 /*@
8823    MatIsHermitian - Test whether a matrix is Hermitian
8824 
8825    Collective on Mat
8826 
8827    Input Parameters:
8828 +  A - the matrix to test
8829 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8830 
8831    Output Parameters:
8832 .  flg - the result
8833 
8834    Level: intermediate
8835 
8836    Notes:
8837     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8838 
8839     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
8840 
8841     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8842     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
8843 
8844 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8845           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8846 @*/
8847 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) {
8848   PetscFunctionBegin;
8849   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8850   PetscValidBoolPointer(flg, 3);
8851 
8852   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8853   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8854   else {
8855     if (!A->ops->ishermitian) {
8856       MatType mattype;
8857       PetscCall(MatGetType(A, &mattype));
8858       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8859     }
8860     PetscUseTypeMethod(A, ishermitian, tol, flg);
8861     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
8862   }
8863   PetscFunctionReturn(0);
8864 }
8865 
8866 /*@
8867    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
8868 
8869    Not Collective
8870 
8871    Input Parameter:
8872 .  A - the matrix to check
8873 
8874    Output Parameters:
8875 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8876 -  flg - the result (only valid if set is `PETSC_TRUE`)
8877 
8878    Level: advanced
8879 
8880    Notes:
8881    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8882    if you want it explicitly checked
8883 
8884     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8885     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8886 
8887 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8888 @*/
8889 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) {
8890   PetscFunctionBegin;
8891   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8892   PetscValidBoolPointer(set, 2);
8893   PetscValidBoolPointer(flg, 3);
8894   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8895     *set = PETSC_TRUE;
8896     *flg = PetscBool3ToBool(A->symmetric);
8897   } else {
8898     *set = PETSC_FALSE;
8899   }
8900   PetscFunctionReturn(0);
8901 }
8902 
8903 /*@
8904    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
8905 
8906    Not Collective
8907 
8908    Input Parameter:
8909 .  A - the matrix to check
8910 
8911    Output Parameters:
8912 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8913 -  flg - the result (only valid if set is `PETSC_TRUE`)
8914 
8915    Level: advanced
8916 
8917    Notes:
8918    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
8919 
8920    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
8921    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
8922 
8923 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8924 @*/
8925 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) {
8926   PetscFunctionBegin;
8927   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8928   PetscValidBoolPointer(set, 2);
8929   PetscValidBoolPointer(flg, 3);
8930   if (A->spd != PETSC_BOOL3_UNKNOWN) {
8931     *set = PETSC_TRUE;
8932     *flg = PetscBool3ToBool(A->spd);
8933   } else {
8934     *set = PETSC_FALSE;
8935   }
8936   PetscFunctionReturn(0);
8937 }
8938 
8939 /*@
8940    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
8941 
8942    Not Collective
8943 
8944    Input Parameter:
8945 .  A - the matrix to check
8946 
8947    Output Parameters:
8948 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
8949 -  flg - the result (only valid if set is `PETSC_TRUE`)
8950 
8951    Level: advanced
8952 
8953    Notes:
8954    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
8955    if you want it explicitly checked
8956 
8957    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8958    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8959 
8960 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
8961 @*/
8962 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) {
8963   PetscFunctionBegin;
8964   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8965   PetscValidBoolPointer(set, 2);
8966   PetscValidBoolPointer(flg, 3);
8967   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
8968     *set = PETSC_TRUE;
8969     *flg = PetscBool3ToBool(A->hermitian);
8970   } else {
8971     *set = PETSC_FALSE;
8972   }
8973   PetscFunctionReturn(0);
8974 }
8975 
8976 /*@
8977    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
8978 
8979    Collective on Mat
8980 
8981    Input Parameter:
8982 .  A - the matrix to test
8983 
8984    Output Parameters:
8985 .  flg - the result
8986 
8987    Notes:
8988    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
8989 
8990    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
8991    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8992 
8993    Level: intermediate
8994 
8995 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
8996 @*/
8997 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) {
8998   PetscFunctionBegin;
8999   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9000   PetscValidBoolPointer(flg, 2);
9001   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9002     *flg = PetscBool3ToBool(A->structurally_symmetric);
9003   } else {
9004     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9005     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9006   }
9007   PetscFunctionReturn(0);
9008 }
9009 
9010 /*@
9011    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9012 
9013    Not Collective
9014 
9015    Input Parameter:
9016 .  A - the matrix to check
9017 
9018    Output Parameters:
9019 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9020 -  flg - the result (only valid if set is PETSC_TRUE)
9021 
9022    Level: advanced
9023 
9024    Notes:
9025    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
9026    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9027 
9028    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9029 
9030 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9031 @*/
9032 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) {
9033   PetscFunctionBegin;
9034   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9035   PetscValidBoolPointer(set, 2);
9036   PetscValidBoolPointer(flg, 3);
9037   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9038     *set = PETSC_TRUE;
9039     *flg = PetscBool3ToBool(A->structurally_symmetric);
9040   } else {
9041     *set = PETSC_FALSE;
9042   }
9043   PetscFunctionReturn(0);
9044 }
9045 
9046 /*@
9047    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9048        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9049 
9050     Not collective
9051 
9052    Input Parameter:
9053 .   mat - the matrix
9054 
9055    Output Parameters:
9056 +   nstash   - the size of the stash
9057 .   reallocs - the number of additional mallocs incurred.
9058 .   bnstash   - the size of the block stash
9059 -   breallocs - the number of additional mallocs incurred.in the block stash
9060 
9061    Level: advanced
9062 
9063 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9064 @*/
9065 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) {
9066   PetscFunctionBegin;
9067   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9068   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9069   PetscFunctionReturn(0);
9070 }
9071 
9072 /*@C
9073    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9074    parallel layout, `PetscLayout` for rows and columns
9075 
9076    Collective on mat
9077 
9078    Input Parameter:
9079 .  mat - the matrix
9080 
9081    Output Parameters:
9082 +   right - (optional) vector that the matrix can be multiplied against
9083 -   left - (optional) vector that the matrix vector product can be stored in
9084 
9085    Notes:
9086     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()`.
9087 
9088     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9089 
9090   Level: advanced
9091 
9092 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9093 @*/
9094 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) {
9095   PetscFunctionBegin;
9096   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9097   PetscValidType(mat, 1);
9098   if (mat->ops->getvecs) {
9099     PetscUseTypeMethod(mat, getvecs, right, left);
9100   } else {
9101     PetscInt rbs, cbs;
9102     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9103     if (right) {
9104       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9105       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9106       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9107       PetscCall(VecSetBlockSize(*right, cbs));
9108       PetscCall(VecSetType(*right, mat->defaultvectype));
9109 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9110       if (mat->boundtocpu && mat->bindingpropagates) {
9111         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9112         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9113       }
9114 #endif
9115       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9116     }
9117     if (left) {
9118       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9119       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9120       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9121       PetscCall(VecSetBlockSize(*left, rbs));
9122       PetscCall(VecSetType(*left, mat->defaultvectype));
9123 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9124       if (mat->boundtocpu && mat->bindingpropagates) {
9125         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9126         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9127       }
9128 #endif
9129       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9130     }
9131   }
9132   PetscFunctionReturn(0);
9133 }
9134 
9135 /*@C
9136    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9137      with default values.
9138 
9139    Not Collective
9140 
9141    Input Parameters:
9142 .    info - the `MatFactorInfo` data structure
9143 
9144    Notes:
9145     The solvers are generally used through the `KSP` and `PC` objects, for example
9146           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9147 
9148     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9149 
9150    Level: developer
9151 
9152    Developer Note:
9153    The Fortran interface is not autogenerated as the f90
9154    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9155 
9156 .seealso: `MatGetFactor()`, `MatFactorInfo`
9157 @*/
9158 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) {
9159   PetscFunctionBegin;
9160   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9161   PetscFunctionReturn(0);
9162 }
9163 
9164 /*@
9165    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9166 
9167    Collective on mat
9168 
9169    Input Parameters:
9170 +  mat - the factored matrix
9171 -  is - the index set defining the Schur indices (0-based)
9172 
9173    Notes:
9174     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9175 
9176    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9177 
9178    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9179 
9180    Level: advanced
9181 
9182 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9183           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9184 
9185 @*/
9186 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) {
9187   PetscErrorCode (*f)(Mat, IS);
9188 
9189   PetscFunctionBegin;
9190   PetscValidType(mat, 1);
9191   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9192   PetscValidType(is, 2);
9193   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9194   PetscCheckSameComm(mat, 1, is, 2);
9195   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9196   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9197   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9198   PetscCall(MatDestroy(&mat->schur));
9199   PetscCall((*f)(mat, is));
9200   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9201   PetscFunctionReturn(0);
9202 }
9203 
9204 /*@
9205   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9206 
9207    Logically Collective on mat
9208 
9209    Input Parameters:
9210 +  F - the factored matrix obtained by calling `MatGetFactor()`
9211 .  S - location where to return the Schur complement, can be NULL
9212 -  status - the status of the Schur complement matrix, can be NULL
9213 
9214    Notes:
9215    You must call `MatFactorSetSchurIS()` before calling this routine.
9216 
9217    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9218 
9219    The routine provides a copy of the Schur matrix stored within the solver data structures.
9220    The caller must destroy the object when it is no longer needed.
9221    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9222 
9223    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)
9224 
9225    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9226 
9227    Developer Note:
9228     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9229    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9230 
9231    Level: advanced
9232 
9233 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9234 @*/
9235 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) {
9236   PetscFunctionBegin;
9237   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9238   if (S) PetscValidPointer(S, 2);
9239   if (status) PetscValidPointer(status, 3);
9240   if (S) {
9241     PetscErrorCode (*f)(Mat, Mat *);
9242 
9243     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9244     if (f) {
9245       PetscCall((*f)(F, S));
9246     } else {
9247       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9248     }
9249   }
9250   if (status) *status = F->schur_status;
9251   PetscFunctionReturn(0);
9252 }
9253 
9254 /*@
9255   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9256 
9257    Logically Collective on mat
9258 
9259    Input Parameters:
9260 +  F - the factored matrix obtained by calling `MatGetFactor()`
9261 .  *S - location where to return the Schur complement, can be NULL
9262 -  status - the status of the Schur complement matrix, can be NULL
9263 
9264    Notes:
9265    You must call `MatFactorSetSchurIS()` before calling this routine.
9266 
9267    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9268 
9269    The routine returns a the Schur Complement stored within the data strutures of the solver.
9270 
9271    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9272 
9273    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9274 
9275    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9276 
9277    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9278 
9279    Level: advanced
9280 
9281 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9282 @*/
9283 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) {
9284   PetscFunctionBegin;
9285   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9286   if (S) PetscValidPointer(S, 2);
9287   if (status) PetscValidPointer(status, 3);
9288   if (S) *S = F->schur;
9289   if (status) *status = F->schur_status;
9290   PetscFunctionReturn(0);
9291 }
9292 
9293 /*@
9294   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9295 
9296    Logically Collective on mat
9297 
9298    Input Parameters:
9299 +  F - the factored matrix obtained by calling `MatGetFactor()`
9300 .  *S - location where the Schur complement is stored
9301 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9302 
9303    Level: advanced
9304 
9305 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9306 @*/
9307 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) {
9308   PetscFunctionBegin;
9309   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9310   if (S) {
9311     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9312     *S = NULL;
9313   }
9314   F->schur_status = status;
9315   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9316   PetscFunctionReturn(0);
9317 }
9318 
9319 /*@
9320   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9321 
9322    Logically Collective on mat
9323 
9324    Input Parameters:
9325 +  F - the factored matrix obtained by calling `MatGetFactor()`
9326 .  rhs - location where the right hand side of the Schur complement system is stored
9327 -  sol - location where the solution of the Schur complement system has to be returned
9328 
9329    Notes:
9330    The sizes of the vectors should match the size of the Schur complement
9331 
9332    Must be called after `MatFactorSetSchurIS()`
9333 
9334    Level: advanced
9335 
9336 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9337 @*/
9338 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) {
9339   PetscFunctionBegin;
9340   PetscValidType(F, 1);
9341   PetscValidType(rhs, 2);
9342   PetscValidType(sol, 3);
9343   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9344   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9345   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9346   PetscCheckSameComm(F, 1, rhs, 2);
9347   PetscCheckSameComm(F, 1, sol, 3);
9348   PetscCall(MatFactorFactorizeSchurComplement(F));
9349   switch (F->schur_status) {
9350   case MAT_FACTOR_SCHUR_FACTORED: PetscCall(MatSolveTranspose(F->schur, rhs, sol)); break;
9351   case MAT_FACTOR_SCHUR_INVERTED: PetscCall(MatMultTranspose(F->schur, rhs, sol)); break;
9352   default: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9353   }
9354   PetscFunctionReturn(0);
9355 }
9356 
9357 /*@
9358   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9359 
9360    Logically Collective on mat
9361 
9362    Input Parameters:
9363 +  F - the factored matrix obtained by calling `MatGetFactor()`
9364 .  rhs - location where the right hand side of the Schur complement system is stored
9365 -  sol - location where the solution of the Schur complement system has to be returned
9366 
9367    Notes:
9368    The sizes of the vectors should match the size of the Schur complement
9369 
9370    Must be called after `MatFactorSetSchurIS()`
9371 
9372    Level: advanced
9373 
9374 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9375 @*/
9376 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) {
9377   PetscFunctionBegin;
9378   PetscValidType(F, 1);
9379   PetscValidType(rhs, 2);
9380   PetscValidType(sol, 3);
9381   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9382   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9383   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9384   PetscCheckSameComm(F, 1, rhs, 2);
9385   PetscCheckSameComm(F, 1, sol, 3);
9386   PetscCall(MatFactorFactorizeSchurComplement(F));
9387   switch (F->schur_status) {
9388   case MAT_FACTOR_SCHUR_FACTORED: PetscCall(MatSolve(F->schur, rhs, sol)); break;
9389   case MAT_FACTOR_SCHUR_INVERTED: PetscCall(MatMult(F->schur, rhs, sol)); break;
9390   default: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9391   }
9392   PetscFunctionReturn(0);
9393 }
9394 
9395 /*@
9396   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9397 
9398    Logically Collective on F
9399 
9400    Input Parameters:
9401 .  F - the factored matrix obtained by calling `MatGetFactor()`
9402 
9403    Notes:
9404     Must be called after `MatFactorSetSchurIS()`.
9405 
9406    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9407 
9408    Level: advanced
9409 
9410 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9411 @*/
9412 PetscErrorCode MatFactorInvertSchurComplement(Mat F) {
9413   PetscFunctionBegin;
9414   PetscValidType(F, 1);
9415   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9416   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9417   PetscCall(MatFactorFactorizeSchurComplement(F));
9418   PetscCall(MatFactorInvertSchurComplement_Private(F));
9419   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9420   PetscFunctionReturn(0);
9421 }
9422 
9423 /*@
9424   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9425 
9426    Logically Collective on mat
9427 
9428    Input Parameters:
9429 .  F - the factored matrix obtained by calling `MatGetFactor()`
9430 
9431    Note:
9432     Must be called after `MatFactorSetSchurIS()`
9433 
9434    Level: advanced
9435 
9436 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9437 @*/
9438 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) {
9439   PetscFunctionBegin;
9440   PetscValidType(F, 1);
9441   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9442   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9443   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9444   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9445   PetscFunctionReturn(0);
9446 }
9447 
9448 /*@
9449    MatPtAP - Creates the matrix product C = P^T * A * P
9450 
9451    Neighbor-wise Collective on A
9452 
9453    Input Parameters:
9454 +  A - the matrix
9455 .  P - the projection matrix
9456 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9457 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9458           if the result is a dense matrix this is irrelevant
9459 
9460    Output Parameters:
9461 .  C - the product matrix
9462 
9463    Notes:
9464    C will be created and must be destroyed by the user with `MatDestroy()`.
9465 
9466    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9467 
9468    Developer Note:
9469    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9470 
9471    Level: intermediate
9472 
9473 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9474 @*/
9475 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) {
9476   PetscFunctionBegin;
9477   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9478   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9479 
9480   if (scall == MAT_INITIAL_MATRIX) {
9481     PetscCall(MatProductCreate(A, P, NULL, C));
9482     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9483     PetscCall(MatProductSetAlgorithm(*C, "default"));
9484     PetscCall(MatProductSetFill(*C, fill));
9485 
9486     (*C)->product->api_user = PETSC_TRUE;
9487     PetscCall(MatProductSetFromOptions(*C));
9488     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);
9489     PetscCall(MatProductSymbolic(*C));
9490   } else { /* scall == MAT_REUSE_MATRIX */
9491     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9492   }
9493 
9494   PetscCall(MatProductNumeric(*C));
9495   (*C)->symmetric = A->symmetric;
9496   (*C)->spd       = A->spd;
9497   PetscFunctionReturn(0);
9498 }
9499 
9500 /*@
9501    MatRARt - Creates the matrix product C = R * A * R^T
9502 
9503    Neighbor-wise Collective on A
9504 
9505    Input Parameters:
9506 +  A - the matrix
9507 .  R - the projection matrix
9508 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9509 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9510           if the result is a dense matrix this is irrelevant
9511 
9512    Output Parameters:
9513 .  C - the product matrix
9514 
9515    Notes:
9516    C will be created and must be destroyed by the user with `MatDestroy()`.
9517 
9518    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9519 
9520    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9521    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9522    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9523    We recommend using MatPtAP().
9524 
9525    Level: intermediate
9526 
9527 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9528 @*/
9529 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) {
9530   PetscFunctionBegin;
9531   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9532   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9533 
9534   if (scall == MAT_INITIAL_MATRIX) {
9535     PetscCall(MatProductCreate(A, R, NULL, C));
9536     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9537     PetscCall(MatProductSetAlgorithm(*C, "default"));
9538     PetscCall(MatProductSetFill(*C, fill));
9539 
9540     (*C)->product->api_user = PETSC_TRUE;
9541     PetscCall(MatProductSetFromOptions(*C));
9542     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);
9543     PetscCall(MatProductSymbolic(*C));
9544   } else { /* scall == MAT_REUSE_MATRIX */
9545     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9546   }
9547 
9548   PetscCall(MatProductNumeric(*C));
9549   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9550   PetscFunctionReturn(0);
9551 }
9552 
9553 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) {
9554   PetscFunctionBegin;
9555   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9556 
9557   if (scall == MAT_INITIAL_MATRIX) {
9558     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9559     PetscCall(MatProductCreate(A, B, NULL, C));
9560     PetscCall(MatProductSetType(*C, ptype));
9561     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9562     PetscCall(MatProductSetFill(*C, fill));
9563 
9564     (*C)->product->api_user = PETSC_TRUE;
9565     PetscCall(MatProductSetFromOptions(*C));
9566     PetscCall(MatProductSymbolic(*C));
9567   } else { /* scall == MAT_REUSE_MATRIX */
9568     Mat_Product *product = (*C)->product;
9569     PetscBool    isdense;
9570 
9571     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9572     if (isdense && product && product->type != ptype) {
9573       PetscCall(MatProductClear(*C));
9574       product = NULL;
9575     }
9576     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9577     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9578       if (isdense) {
9579         PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9580         product           = (*C)->product;
9581         product->fill     = fill;
9582         product->api_user = PETSC_TRUE;
9583         product->clear    = PETSC_TRUE;
9584 
9585         PetscCall(MatProductSetType(*C, ptype));
9586         PetscCall(MatProductSetFromOptions(*C));
9587         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);
9588         PetscCall(MatProductSymbolic(*C));
9589       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9590     } else { /* user may change input matrices A or B when REUSE */
9591       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9592     }
9593   }
9594   PetscCall(MatProductNumeric(*C));
9595   PetscFunctionReturn(0);
9596 }
9597 
9598 /*@
9599    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9600 
9601    Neighbor-wise Collective on A
9602 
9603    Input Parameters:
9604 +  A - the left matrix
9605 .  B - the right matrix
9606 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9607 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9608           if the result is a dense matrix this is irrelevant
9609 
9610    Output Parameters:
9611 .  C - the product matrix
9612 
9613    Notes:
9614    Unless scall is `MAT_REUSE_MATRIX` C will be created.
9615 
9616    `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
9617    call to this function with `MAT_INITIAL_MATRIX`.
9618 
9619    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9620 
9621    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`,
9622    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9623 
9624    Example of Usage:
9625 .vb
9626      MatProductCreate(A,B,NULL,&C);
9627      MatProductSetType(C,MATPRODUCT_AB);
9628      MatProductSymbolic(C);
9629      MatProductNumeric(C); // compute C=A * B
9630      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9631      MatProductNumeric(C);
9632      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9633      MatProductNumeric(C);
9634 .ve
9635 
9636    Level: intermediate
9637 
9638 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9639 @*/
9640 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9641   PetscFunctionBegin;
9642   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
9643   PetscFunctionReturn(0);
9644 }
9645 
9646 /*@
9647    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9648 
9649    Neighbor-wise Collective on A
9650 
9651    Input Parameters:
9652 +  A - the left matrix
9653 .  B - the right matrix
9654 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9655 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9656 
9657    Output Parameters:
9658 .  C - the product matrix
9659 
9660    Notes:
9661    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9662 
9663    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9664 
9665    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9666    actually needed.
9667 
9668    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9669    and for pairs of `MATMPIDENSE` matrices.
9670 
9671    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9672 
9673    Options Database Keys:
9674 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9675               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9676               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9677 
9678    Level: intermediate
9679 
9680 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9681 @*/
9682 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9683   PetscFunctionBegin;
9684   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
9685   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9686   PetscFunctionReturn(0);
9687 }
9688 
9689 /*@
9690    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9691 
9692    Neighbor-wise Collective on A
9693 
9694    Input Parameters:
9695 +  A - the left matrix
9696 .  B - the right matrix
9697 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9698 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9699 
9700    Output Parameters:
9701 .  C - the product matrix
9702 
9703    Notes:
9704    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9705 
9706    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9707 
9708    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9709 
9710    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9711    actually needed.
9712 
9713    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9714    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
9715 
9716    Level: intermediate
9717 
9718 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9719 @*/
9720 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9721   PetscFunctionBegin;
9722   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
9723   PetscFunctionReturn(0);
9724 }
9725 
9726 /*@
9727    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
9728 
9729    Neighbor-wise Collective on A
9730 
9731    Input Parameters:
9732 +  A - the left matrix
9733 .  B - the middle matrix
9734 .  C - the right matrix
9735 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9736 -  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
9737           if the result is a dense matrix this is irrelevant
9738 
9739    Output Parameters:
9740 .  D - the product matrix
9741 
9742    Notes:
9743    Unless scall is `MAT_REUSE_MATRIX` D will be created.
9744 
9745    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9746 
9747    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
9748 
9749    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9750    actually needed.
9751 
9752    If you have many matrices with the same non-zero structure to multiply, you
9753    should use `MAT_REUSE_MATRIX` in all calls but the first
9754 
9755    Level: intermediate
9756 
9757 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9758 @*/
9759 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) {
9760   PetscFunctionBegin;
9761   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
9762   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9763 
9764   if (scall == MAT_INITIAL_MATRIX) {
9765     PetscCall(MatProductCreate(A, B, C, D));
9766     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
9767     PetscCall(MatProductSetAlgorithm(*D, "default"));
9768     PetscCall(MatProductSetFill(*D, fill));
9769 
9770     (*D)->product->api_user = PETSC_TRUE;
9771     PetscCall(MatProductSetFromOptions(*D));
9772     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,
9773                ((PetscObject)C)->type_name);
9774     PetscCall(MatProductSymbolic(*D));
9775   } else { /* user may change input matrices when REUSE */
9776     PetscCall(MatProductReplaceMats(A, B, C, *D));
9777   }
9778   PetscCall(MatProductNumeric(*D));
9779   PetscFunctionReturn(0);
9780 }
9781 
9782 /*@
9783    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9784 
9785    Collective on mat
9786 
9787    Input Parameters:
9788 +  mat - the matrix
9789 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9790 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9791 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9792 
9793    Output Parameter:
9794 .  matredundant - redundant matrix
9795 
9796    Notes:
9797    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9798    original matrix has not changed from that last call to MatCreateRedundantMatrix().
9799 
9800    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9801    calling it.
9802 
9803    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
9804 
9805    Level: advanced
9806 
9807 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9808 @*/
9809 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) {
9810   MPI_Comm       comm;
9811   PetscMPIInt    size;
9812   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9813   Mat_Redundant *redund     = NULL;
9814   PetscSubcomm   psubcomm   = NULL;
9815   MPI_Comm       subcomm_in = subcomm;
9816   Mat           *matseq;
9817   IS             isrow, iscol;
9818   PetscBool      newsubcomm = PETSC_FALSE;
9819 
9820   PetscFunctionBegin;
9821   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9822   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9823     PetscValidPointer(*matredundant, 5);
9824     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
9825   }
9826 
9827   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9828   if (size == 1 || nsubcomm == 1) {
9829     if (reuse == MAT_INITIAL_MATRIX) {
9830       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
9831     } else {
9832       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");
9833       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
9834     }
9835     PetscFunctionReturn(0);
9836   }
9837 
9838   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9839   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9840   MatCheckPreallocated(mat, 1);
9841 
9842   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
9843   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9844     /* create psubcomm, then get subcomm */
9845     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
9846     PetscCallMPI(MPI_Comm_size(comm, &size));
9847     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
9848 
9849     PetscCall(PetscSubcommCreate(comm, &psubcomm));
9850     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
9851     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
9852     PetscCall(PetscSubcommSetFromOptions(psubcomm));
9853     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
9854     newsubcomm = PETSC_TRUE;
9855     PetscCall(PetscSubcommDestroy(&psubcomm));
9856   }
9857 
9858   /* get isrow, iscol and a local sequential matrix matseq[0] */
9859   if (reuse == MAT_INITIAL_MATRIX) {
9860     mloc_sub = PETSC_DECIDE;
9861     nloc_sub = PETSC_DECIDE;
9862     if (bs < 1) {
9863       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
9864       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
9865     } else {
9866       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
9867       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
9868     }
9869     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
9870     rstart = rend - mloc_sub;
9871     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
9872     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
9873   } else { /* reuse == MAT_REUSE_MATRIX */
9874     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");
9875     /* retrieve subcomm */
9876     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
9877     redund = (*matredundant)->redundant;
9878     isrow  = redund->isrow;
9879     iscol  = redund->iscol;
9880     matseq = redund->matseq;
9881   }
9882   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
9883 
9884   /* get matredundant over subcomm */
9885   if (reuse == MAT_INITIAL_MATRIX) {
9886     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
9887 
9888     /* create a supporting struct and attach it to C for reuse */
9889     PetscCall(PetscNewLog(*matredundant, &redund));
9890     (*matredundant)->redundant = redund;
9891     redund->isrow              = isrow;
9892     redund->iscol              = iscol;
9893     redund->matseq             = matseq;
9894     if (newsubcomm) {
9895       redund->subcomm = subcomm;
9896     } else {
9897       redund->subcomm = MPI_COMM_NULL;
9898     }
9899   } else {
9900     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
9901   }
9902 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9903   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9904     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
9905     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
9906   }
9907 #endif
9908   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
9909   PetscFunctionReturn(0);
9910 }
9911 
9912 /*@C
9913    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
9914    a given `Mat`. Each submatrix can span multiple procs.
9915 
9916    Collective on mat
9917 
9918    Input Parameters:
9919 +  mat - the matrix
9920 .  subcomm - the subcommunicator obtained by MPI_Com_split(comm)
9921 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9922 
9923    Output Parameter:
9924 .  subMat - 'parallel submatrices each spans a given subcomm
9925 
9926   Notes:
9927   The submatrix partition across processors is dictated by 'subComm' a
9928   communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
9929   is not restriced to be grouped with consecutive original ranks.
9930 
9931   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
9932   map directly to the layout of the original matrix [wrt the local
9933   row,col partitioning]. So the original 'DiagonalMat' naturally maps
9934   into the 'DiagonalMat' of the subMat, hence it is used directly from
9935   the subMat. However the offDiagMat looses some columns - and this is
9936   reconstructed with `MatSetValues()`
9937 
9938   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
9939 
9940   Level: advanced
9941 
9942 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
9943 @*/
9944 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) {
9945   PetscMPIInt commsize, subCommSize;
9946 
9947   PetscFunctionBegin;
9948   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
9949   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
9950   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
9951 
9952   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");
9953   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
9954   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
9955   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
9956   PetscFunctionReturn(0);
9957 }
9958 
9959 /*@
9960    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
9961 
9962    Not Collective
9963 
9964    Input Parameters:
9965 +  mat - matrix to extract local submatrix from
9966 .  isrow - local row indices for submatrix
9967 -  iscol - local column indices for submatrix
9968 
9969    Output Parameter:
9970 .  submat - the submatrix
9971 
9972    Level: intermediate
9973 
9974    Notes:
9975    The submat should be returned with `MatRestoreLocalSubMatrix()`.
9976 
9977    Depending on the format of mat, the returned submat may not implement `MatMult()`.  Its communicator may be
9978    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
9979 
9980    The submat always implements `MatSetValuesLocal()`.  If isrow and iscol have the same block size, then
9981    `MatSetValuesBlockedLocal()` will also be implemented.
9982 
9983    The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
9984    Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
9985 
9986 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
9987 @*/
9988 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) {
9989   PetscFunctionBegin;
9990   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9991   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
9992   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
9993   PetscCheckSameComm(isrow, 2, iscol, 3);
9994   PetscValidPointer(submat, 4);
9995   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
9996 
9997   if (mat->ops->getlocalsubmatrix) {
9998     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
9999   } else {
10000     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10001   }
10002   PetscFunctionReturn(0);
10003 }
10004 
10005 /*@
10006    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10007 
10008    Not Collective
10009 
10010    Input Parameters:
10011 +  mat - matrix to extract local submatrix from
10012 .  isrow - local row indices for submatrix
10013 .  iscol - local column indices for submatrix
10014 -  submat - the submatrix
10015 
10016    Level: intermediate
10017 
10018 .seealso: `MatGetLocalSubMatrix()`
10019 @*/
10020 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) {
10021   PetscFunctionBegin;
10022   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10023   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10024   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10025   PetscCheckSameComm(isrow, 2, iscol, 3);
10026   PetscValidPointer(submat, 4);
10027   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10028 
10029   if (mat->ops->restorelocalsubmatrix) {
10030     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10031   } else {
10032     PetscCall(MatDestroy(submat));
10033   }
10034   *submat = NULL;
10035   PetscFunctionReturn(0);
10036 }
10037 
10038 /* --------------------------------------------------------*/
10039 /*@
10040    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10041 
10042    Collective on mat
10043 
10044    Input Parameter:
10045 .  mat - the matrix
10046 
10047    Output Parameter:
10048 .  is - if any rows have zero diagonals this contains the list of them
10049 
10050    Level: developer
10051 
10052 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10053 @*/
10054 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) {
10055   PetscFunctionBegin;
10056   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10057   PetscValidType(mat, 1);
10058   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10059   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10060 
10061   if (!mat->ops->findzerodiagonals) {
10062     Vec                diag;
10063     const PetscScalar *a;
10064     PetscInt          *rows;
10065     PetscInt           rStart, rEnd, r, nrow = 0;
10066 
10067     PetscCall(MatCreateVecs(mat, &diag, NULL));
10068     PetscCall(MatGetDiagonal(mat, diag));
10069     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10070     PetscCall(VecGetArrayRead(diag, &a));
10071     for (r = 0; r < rEnd - rStart; ++r)
10072       if (a[r] == 0.0) ++nrow;
10073     PetscCall(PetscMalloc1(nrow, &rows));
10074     nrow = 0;
10075     for (r = 0; r < rEnd - rStart; ++r)
10076       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10077     PetscCall(VecRestoreArrayRead(diag, &a));
10078     PetscCall(VecDestroy(&diag));
10079     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10080   } else {
10081     PetscUseTypeMethod(mat, findzerodiagonals, is);
10082   }
10083   PetscFunctionReturn(0);
10084 }
10085 
10086 /*@
10087    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10088 
10089    Collective on mat
10090 
10091    Input Parameter:
10092 .  mat - the matrix
10093 
10094    Output Parameter:
10095 .  is - contains the list of rows with off block diagonal entries
10096 
10097    Level: developer
10098 
10099 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10100 @*/
10101 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) {
10102   PetscFunctionBegin;
10103   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10104   PetscValidType(mat, 1);
10105   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10106   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10107 
10108   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10109   PetscFunctionReturn(0);
10110 }
10111 
10112 /*@C
10113   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10114 
10115   Collective on mat
10116 
10117   Input Parameters:
10118 . mat - the matrix
10119 
10120   Output Parameters:
10121 . values - the block inverses in column major order (FORTRAN-like)
10122 
10123    Notes:
10124    The size of the blocks is determined by the block size of the matrix.
10125 
10126    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10127 
10128    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10129 
10130    Fortran Note:
10131      This routine is not available from Fortran.
10132 
10133   Level: advanced
10134 
10135 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10136 @*/
10137 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) {
10138   PetscFunctionBegin;
10139   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10140   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10141   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10142   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10143   PetscFunctionReturn(0);
10144 }
10145 
10146 /*@C
10147   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10148 
10149   Collective on mat
10150 
10151   Input Parameters:
10152 + mat - the matrix
10153 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10154 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10155 
10156   Output Parameters:
10157 . values - the block inverses in column major order (FORTRAN-like)
10158 
10159   Notes:
10160   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10161 
10162   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10163 
10164   Fortran Note:
10165   This routine is not available from Fortran.
10166 
10167   Level: advanced
10168 
10169 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10170 @*/
10171 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) {
10172   PetscFunctionBegin;
10173   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10174   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10175   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10176   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10177   PetscFunctionReturn(0);
10178 }
10179 
10180 /*@
10181   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10182 
10183   Collective on Mat
10184 
10185   Input Parameters:
10186 + A - the matrix
10187 - C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10188 
10189   Note:
10190   The blocksize of the matrix is used to determine the blocks on the diagonal of C
10191 
10192   Level: advanced
10193 
10194 .seealso: `MatInvertBlockDiagonal()`
10195 @*/
10196 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) {
10197   const PetscScalar *vals;
10198   PetscInt          *dnnz;
10199   PetscInt           m, rstart, rend, bs, i, j;
10200 
10201   PetscFunctionBegin;
10202   PetscCall(MatInvertBlockDiagonal(A, &vals));
10203   PetscCall(MatGetBlockSize(A, &bs));
10204   PetscCall(MatGetLocalSize(A, &m, NULL));
10205   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10206   PetscCall(PetscMalloc1(m / bs, &dnnz));
10207   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10208   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10209   PetscCall(PetscFree(dnnz));
10210   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10211   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10212   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10213   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10214   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10215   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10216   PetscFunctionReturn(0);
10217 }
10218 
10219 /*@C
10220     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10221     via `MatTransposeColoringCreate()`.
10222 
10223     Collective on c
10224 
10225     Input Parameter:
10226 .   c - coloring context
10227 
10228     Level: intermediate
10229 
10230 .seealso: `MatTransposeColoringCreate()`
10231 @*/
10232 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) {
10233   MatTransposeColoring matcolor = *c;
10234 
10235   PetscFunctionBegin;
10236   if (!matcolor) PetscFunctionReturn(0);
10237   if (--((PetscObject)matcolor)->refct > 0) {
10238     matcolor = NULL;
10239     PetscFunctionReturn(0);
10240   }
10241 
10242   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10243   PetscCall(PetscFree(matcolor->rows));
10244   PetscCall(PetscFree(matcolor->den2sp));
10245   PetscCall(PetscFree(matcolor->colorforcol));
10246   PetscCall(PetscFree(matcolor->columns));
10247   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10248   PetscCall(PetscHeaderDestroy(c));
10249   PetscFunctionReturn(0);
10250 }
10251 
10252 /*@C
10253     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10254     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10255     `MatTransposeColoring` to sparse B.
10256 
10257     Collective on coloring
10258 
10259     Input Parameters:
10260 +   B - sparse matrix B
10261 .   Btdense - symbolic dense matrix B^T
10262 -   coloring - coloring context created with `MatTransposeColoringCreate()`
10263 
10264     Output Parameter:
10265 .   Btdense - dense matrix B^T
10266 
10267     Level: developer
10268 
10269     Note:
10270     These are used internally for some implementations of `MatRARt()`
10271 
10272 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10273 
10274 @*/
10275 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) {
10276   PetscFunctionBegin;
10277   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10278   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10279   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10280 
10281   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10282   PetscFunctionReturn(0);
10283 }
10284 
10285 /*@C
10286     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10287     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10288     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10289     Csp from Cden.
10290 
10291     Collective on matcoloring
10292 
10293     Input Parameters:
10294 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10295 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10296 
10297     Output Parameter:
10298 .   Csp - sparse matrix
10299 
10300     Level: developer
10301 
10302     Note:
10303     These are used internally for some implementations of `MatRARt()`
10304 
10305 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10306 
10307 @*/
10308 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) {
10309   PetscFunctionBegin;
10310   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10311   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10312   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10313 
10314   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10315   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10316   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10317   PetscFunctionReturn(0);
10318 }
10319 
10320 /*@C
10321    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10322 
10323    Collective on mat
10324 
10325    Input Parameters:
10326 +  mat - the matrix product C
10327 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10328 
10329     Output Parameter:
10330 .   color - the new coloring context
10331 
10332     Level: intermediate
10333 
10334 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10335           `MatTransColoringApplyDenToSp()`
10336 @*/
10337 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) {
10338   MatTransposeColoring c;
10339   MPI_Comm             comm;
10340 
10341   PetscFunctionBegin;
10342   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10343   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10344   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10345 
10346   c->ctype = iscoloring->ctype;
10347   if (mat->ops->transposecoloringcreate) {
10348     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10349   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10350 
10351   *color = c;
10352   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10353   PetscFunctionReturn(0);
10354 }
10355 
10356 /*@
10357       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10358         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10359         same, otherwise it will be larger
10360 
10361      Not Collective
10362 
10363   Input Parameter:
10364 .    A  - the matrix
10365 
10366   Output Parameter:
10367 .    state - the current state
10368 
10369   Notes:
10370     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10371          different matrices
10372 
10373     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10374 
10375     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10376 
10377   Level: intermediate
10378 
10379 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10380 @*/
10381 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) {
10382   PetscFunctionBegin;
10383   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10384   *state = mat->nonzerostate;
10385   PetscFunctionReturn(0);
10386 }
10387 
10388 /*@
10389       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10390                  matrices from each processor
10391 
10392     Collective
10393 
10394    Input Parameters:
10395 +    comm - the communicators the parallel matrix will live on
10396 .    seqmat - the input sequential matrices
10397 .    n - number of local columns (or `PETSC_DECIDE`)
10398 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10399 
10400    Output Parameter:
10401 .    mpimat - the parallel matrix generated
10402 
10403     Level: developer
10404 
10405    Note:
10406     The number of columns of the matrix in EACH processor MUST be the same.
10407 
10408 .seealso: `Mat`
10409 @*/
10410 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) {
10411   PetscMPIInt size;
10412 
10413   PetscFunctionBegin;
10414   PetscCallMPI(MPI_Comm_size(comm, &size));
10415   if (size == 1) {
10416     if (reuse == MAT_INITIAL_MATRIX) {
10417       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10418     } else {
10419       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10420     }
10421     PetscFunctionReturn(0);
10422   }
10423 
10424   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");
10425 
10426   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10427   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10428   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10429   PetscFunctionReturn(0);
10430 }
10431 
10432 /*@
10433      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10434 
10435     Collective on A
10436 
10437    Input Parameters:
10438 +    A   - the matrix to create subdomains from
10439 -    N   - requested number of subdomains
10440 
10441    Output Parameters:
10442 +    n   - number of subdomains resulting on this rank
10443 -    iss - `IS` list with indices of subdomains on this rank
10444 
10445     Level: advanced
10446 
10447     Note:
10448     The number of subdomains must be smaller than the communicator size
10449 
10450 .seealso: `Mat`, `IS`
10451 @*/
10452 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) {
10453   MPI_Comm    comm, subcomm;
10454   PetscMPIInt size, rank, color;
10455   PetscInt    rstart, rend, k;
10456 
10457   PetscFunctionBegin;
10458   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10459   PetscCallMPI(MPI_Comm_size(comm, &size));
10460   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10461   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);
10462   *n    = 1;
10463   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10464   color = rank / k;
10465   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10466   PetscCall(PetscMalloc1(1, iss));
10467   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10468   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10469   PetscCallMPI(MPI_Comm_free(&subcomm));
10470   PetscFunctionReturn(0);
10471 }
10472 
10473 /*@
10474    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10475 
10476    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10477    If they are not the same, uses `MatMatMatMult()`.
10478 
10479    Once the coarse grid problem is constructed, correct for interpolation operators
10480    that are not of full rank, which can legitimately happen in the case of non-nested
10481    geometric multigrid.
10482 
10483    Input Parameters:
10484 +  restrct - restriction operator
10485 .  dA - fine grid matrix
10486 .  interpolate - interpolation operator
10487 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10488 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10489 
10490    Output Parameters:
10491 .  A - the Galerkin coarse matrix
10492 
10493    Options Database Key:
10494 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10495 
10496    Level: developer
10497 
10498 .seealso: `MatPtAP()`, `MatMatMatMult()`
10499 @*/
10500 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) {
10501   IS  zerorows;
10502   Vec diag;
10503 
10504   PetscFunctionBegin;
10505   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10506   /* Construct the coarse grid matrix */
10507   if (interpolate == restrct) {
10508     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10509   } else {
10510     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10511   }
10512 
10513   /* If the interpolation matrix is not of full rank, A will have zero rows.
10514      This can legitimately happen in the case of non-nested geometric multigrid.
10515      In that event, we set the rows of the matrix to the rows of the identity,
10516      ignoring the equations (as the RHS will also be zero). */
10517 
10518   PetscCall(MatFindZeroRows(*A, &zerorows));
10519 
10520   if (zerorows != NULL) { /* if there are any zero rows */
10521     PetscCall(MatCreateVecs(*A, &diag, NULL));
10522     PetscCall(MatGetDiagonal(*A, diag));
10523     PetscCall(VecISSet(diag, zerorows, 1.0));
10524     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10525     PetscCall(VecDestroy(&diag));
10526     PetscCall(ISDestroy(&zerorows));
10527   }
10528   PetscFunctionReturn(0);
10529 }
10530 
10531 /*@C
10532     MatSetOperation - Allows user to set a matrix operation for any matrix type
10533 
10534    Logically Collective on mat
10535 
10536     Input Parameters:
10537 +   mat - the matrix
10538 .   op - the name of the operation
10539 -   f - the function that provides the operation
10540 
10541    Level: developer
10542 
10543     Usage:
10544 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10545 $      PetscCall(MatCreateXXX(comm,...&A);
10546 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10547 
10548     Notes:
10549     See the file include/petscmat.h for a complete list of matrix
10550     operations, which all have the form MATOP_<OPERATION>, where
10551     <OPERATION> is the name (in all capital letters) of the
10552     user interface routine (e.g., MatMult() -> MATOP_MULT).
10553 
10554     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10555     sequence as the usual matrix interface routines, since they
10556     are intended to be accessed via the usual matrix interface
10557     routines, e.g.,
10558 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10559 
10560     In particular each function MUST return an error code of 0 on success and
10561     nonzero on failure.
10562 
10563     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10564 
10565 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10566 @*/
10567 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) {
10568   PetscFunctionBegin;
10569   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10570   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10571   (((void (**)(void))mat->ops)[op]) = f;
10572   PetscFunctionReturn(0);
10573 }
10574 
10575 /*@C
10576     MatGetOperation - Gets a matrix operation for any matrix type.
10577 
10578     Not Collective
10579 
10580     Input Parameters:
10581 +   mat - the matrix
10582 -   op - the name of the operation
10583 
10584     Output Parameter:
10585 .   f - the function that provides the operation
10586 
10587     Level: developer
10588 
10589     Usage:
10590 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10591 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10592 
10593     Notes:
10594     See the file include/petscmat.h for a complete list of matrix
10595     operations, which all have the form MATOP_<OPERATION>, where
10596     <OPERATION> is the name (in all capital letters) of the
10597     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10598 
10599     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10600 
10601 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10602 @*/
10603 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) {
10604   PetscFunctionBegin;
10605   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10606   *f = (((void (**)(void))mat->ops)[op]);
10607   PetscFunctionReturn(0);
10608 }
10609 
10610 /*@
10611     MatHasOperation - Determines whether the given matrix supports the particular operation.
10612 
10613    Not Collective
10614 
10615    Input Parameters:
10616 +  mat - the matrix
10617 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
10618 
10619    Output Parameter:
10620 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
10621 
10622    Level: advanced
10623 
10624    Note:
10625    See the file include/petscmat.h for a complete list of matrix
10626    operations, which all have the form MATOP_<OPERATION>, where
10627    <OPERATION> is the name (in all capital letters) of the
10628    user-level routine.  E.g., `MatNorm()` -> `MATOP_NORM`.
10629 
10630 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10631 @*/
10632 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) {
10633   PetscFunctionBegin;
10634   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10635   PetscValidBoolPointer(has, 3);
10636   if (mat->ops->hasoperation) {
10637     PetscUseTypeMethod(mat, hasoperation, op, has);
10638   } else {
10639     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10640     else {
10641       *has = PETSC_FALSE;
10642       if (op == MATOP_CREATE_SUBMATRIX) {
10643         PetscMPIInt size;
10644 
10645         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10646         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
10647       }
10648     }
10649   }
10650   PetscFunctionReturn(0);
10651 }
10652 
10653 /*@
10654     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10655 
10656    Collective on mat
10657 
10658    Input Parameters:
10659 .  mat - the matrix
10660 
10661    Output Parameter:
10662 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
10663 
10664    Level: beginner
10665 
10666 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10667 @*/
10668 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) {
10669   PetscFunctionBegin;
10670   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10671   PetscValidType(mat, 1);
10672   PetscValidBoolPointer(cong, 2);
10673   if (!mat->rmap || !mat->cmap) {
10674     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10675     PetscFunctionReturn(0);
10676   }
10677   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10678     PetscCall(PetscLayoutSetUp(mat->rmap));
10679     PetscCall(PetscLayoutSetUp(mat->cmap));
10680     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
10681     if (*cong) mat->congruentlayouts = 1;
10682     else mat->congruentlayouts = 0;
10683   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10684   PetscFunctionReturn(0);
10685 }
10686 
10687 PetscErrorCode MatSetInf(Mat A) {
10688   PetscFunctionBegin;
10689   PetscUseTypeMethod(A, setinf);
10690   PetscFunctionReturn(0);
10691 }
10692 
10693 /*C
10694    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
10695 
10696    Collective on mat
10697 
10698    Input Parameters:
10699 +  A - the matrix
10700 -  sym - `PETSC_TRUE` indicates that the graph will be symmetrized
10701 .  scale - `PETSC_TRUE` indicates that the graph will be scaled with the diagonal
10702 
10703    Output Parameter:
10704 .  graph - the resulting graph
10705 
10706    Level: advanced
10707 
10708 .seealso: `MatCreate()`, `MatFilter()`
10709 */
10710 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, Mat *graph) {
10711   PetscFunctionBegin;
10712   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
10713   PetscValidType(A, 1);
10714   PetscValidPointer(graph, 3);
10715   PetscUseTypeMethod(A, creategraph, sym, scale, graph);
10716   PetscFunctionReturn(0);
10717 }
10718 
10719 /*C
10720    MatFilter - filters a matrices values with an absolut value equal to or below a give threshold
10721 
10722    Collective on mat
10723 
10724    Input Parameter:
10725 .  value - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries <= value
10726 
10727    Input/Output Parameter:
10728 .  A - the `Mat` to filter in place
10729 
10730    Level: developer
10731 
10732    Note:
10733    This is called before graph coarsers are called in `PCGAMG`
10734 
10735 .seealso: `MatCreate()`, `MatCreateGraph()`
10736 */
10737 PETSC_EXTERN PetscErrorCode MatFilter(Mat G, PetscReal value, Mat *F) {
10738   PetscFunctionBegin;
10739   PetscValidHeaderSpecific(G, MAT_CLASSID, 1);
10740   PetscValidType(G, 1);
10741   PetscValidPointer(F, 3);
10742   if (value >= 0.0) PetscCall((G->ops->filter)(G, value, F));
10743   PetscFunctionReturn(0);
10744 }
10745