xref: /petsc/src/mat/interface/matrix.c (revision 6797ed33bfc5684cca29e5d9b9bbfc6c8aac93e0)
1 /*
2    This is where the abstract matrix operations are defined
3 */
4 
5 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
6 #include <petsc/private/isimpl.h>
7 #include <petsc/private/vecimpl.h>
8 
9 /* Logging support */
10 PetscClassId MAT_CLASSID;
11 PetscClassId MAT_COLORING_CLASSID;
12 PetscClassId MAT_FDCOLORING_CLASSID;
13 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
14 
15 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
16 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
17 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
18 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
19 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
20 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
21 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
22 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
23 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
24 PetscLogEvent MAT_TransposeColoringCreate;
25 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
26 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
27 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
28 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
29 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
30 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
31 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
32 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
33 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
34 PetscLogEvent MAT_GetMultiProcBlock;
35 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
36 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
37 PetscLogEvent MAT_SetValuesBatch;
38 PetscLogEvent MAT_ViennaCLCopyToGPU;
39 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
40 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
41 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
42 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
43 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
44 
45 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
46 
47 /*@
48    MatSetRandom - Sets all components of a matrix to random numbers. For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
49                   for sparse matrices that already have locations it fills the locations with random numbers
50 
51    Logically Collective on mat
52 
53    Input Parameters:
54 +  x  - the matrix
55 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or NULL and
56           it will create one internally.
57 
58    Output Parameter:
59 .  x  - the matrix
60 
61    Example of Usage:
62 .vb
63      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
64      MatSetRandom(x,rctx);
65      PetscRandomDestroy(rctx);
66 .ve
67 
68    Level: intermediate
69 
70 .seealso: `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
71 @*/
72 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx) {
73   PetscRandom randObj = NULL;
74 
75   PetscFunctionBegin;
76   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
77   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
78   PetscValidType(x, 1);
79   MatCheckPreallocated(x, 1);
80 
81   if (!rctx) {
82     MPI_Comm comm;
83     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
84     PetscCall(PetscRandomCreate(comm, &randObj));
85     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
86     PetscCall(PetscRandomSetFromOptions(randObj));
87     rctx = randObj;
88   }
89   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
90   PetscUseTypeMethod(x, setrandom, rctx);
91   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
92 
93   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
94   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
95   PetscCall(PetscRandomDestroy(&randObj));
96   PetscFunctionReturn(0);
97 }
98 
99 /*@
100    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
101 
102    Logically Collective on mat
103 
104    Input Parameter:
105 .  mat - the factored matrix
106 
107    Output Parameters:
108 +  pivot - the pivot value computed
109 -  row - the row that the zero pivot occurred. Note that this row must be interpreted carefully due to row reorderings and which processes
110          the share the matrix
111 
112    Level: advanced
113 
114    Notes:
115     This routine does not work for factorizations done with external packages.
116 
117     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
118 
119     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
120 
121 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
122           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
123 @*/
124 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row) {
125   PetscFunctionBegin;
126   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
127   PetscValidRealPointer(pivot, 2);
128   PetscValidIntPointer(row, 3);
129   *pivot = mat->factorerror_zeropivot_value;
130   *row   = mat->factorerror_zeropivot_row;
131   PetscFunctionReturn(0);
132 }
133 
134 /*@
135    MatFactorGetError - gets the error code from a factorization
136 
137    Logically Collective on mat
138 
139    Input Parameters:
140 .  mat - the factored matrix
141 
142    Output Parameter:
143 .  err  - the error code
144 
145    Level: advanced
146 
147    Note:
148     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
149 
150 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
151           `MatFactorError`
152 @*/
153 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err) {
154   PetscFunctionBegin;
155   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
156   PetscValidPointer(err, 2);
157   *err = mat->factorerrortype;
158   PetscFunctionReturn(0);
159 }
160 
161 /*@
162    MatFactorClearError - clears the error code in a factorization
163 
164    Logically Collective on mat
165 
166    Input Parameter:
167 .  mat - the factored matrix
168 
169    Level: developer
170 
171    Note:
172     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
173 
174 .seealso: `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
175           `MatGetErrorCode()`, `MatFactorError`
176 @*/
177 PetscErrorCode MatFactorClearError(Mat mat) {
178   PetscFunctionBegin;
179   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
180   mat->factorerrortype             = MAT_FACTOR_NOERROR;
181   mat->factorerror_zeropivot_value = 0.0;
182   mat->factorerror_zeropivot_row   = 0;
183   PetscFunctionReturn(0);
184 }
185 
186 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero) {
187   Vec                r, l;
188   const PetscScalar *al;
189   PetscInt           i, nz, gnz, N, n;
190 
191   PetscFunctionBegin;
192   PetscCall(MatCreateVecs(mat, &r, &l));
193   if (!cols) { /* nonzero rows */
194     PetscCall(MatGetSize(mat, &N, NULL));
195     PetscCall(MatGetLocalSize(mat, &n, NULL));
196     PetscCall(VecSet(l, 0.0));
197     PetscCall(VecSetRandom(r, NULL));
198     PetscCall(MatMult(mat, r, l));
199     PetscCall(VecGetArrayRead(l, &al));
200   } else { /* nonzero columns */
201     PetscCall(MatGetSize(mat, NULL, &N));
202     PetscCall(MatGetLocalSize(mat, NULL, &n));
203     PetscCall(VecSet(r, 0.0));
204     PetscCall(VecSetRandom(l, NULL));
205     PetscCall(MatMultTranspose(mat, l, r));
206     PetscCall(VecGetArrayRead(r, &al));
207   }
208   if (tol <= 0.0) {
209     for (i = 0, nz = 0; i < n; i++)
210       if (al[i] != 0.0) nz++;
211   } else {
212     for (i = 0, nz = 0; i < n; i++)
213       if (PetscAbsScalar(al[i]) > tol) nz++;
214   }
215   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
216   if (gnz != N) {
217     PetscInt *nzr;
218     PetscCall(PetscMalloc1(nz, &nzr));
219     if (nz) {
220       if (tol < 0) {
221         for (i = 0, nz = 0; i < n; i++)
222           if (al[i] != 0.0) nzr[nz++] = i;
223       } else {
224         for (i = 0, nz = 0; i < n; i++)
225           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
226       }
227     }
228     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
229   } else *nonzero = NULL;
230   if (!cols) { /* nonzero rows */
231     PetscCall(VecRestoreArrayRead(l, &al));
232   } else {
233     PetscCall(VecRestoreArrayRead(r, &al));
234   }
235   PetscCall(VecDestroy(&l));
236   PetscCall(VecDestroy(&r));
237   PetscFunctionReturn(0);
238 }
239 
240 /*@
241       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
242 
243   Input Parameter:
244 .    A  - the matrix
245 
246   Output Parameter:
247 .    keptrows - the rows that are not completely zero
248 
249   Note:
250     keptrows is set to NULL if all rows are nonzero.
251 
252   Level: intermediate
253 
254 .seealso: `Mat`, `MatFindZeroRows()`
255  @*/
256 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows) {
257   PetscFunctionBegin;
258   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
259   PetscValidType(mat, 1);
260   PetscValidPointer(keptrows, 2);
261   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
262   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
263   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
264   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
265   PetscFunctionReturn(0);
266 }
267 
268 /*@
269       MatFindZeroRows - Locate all rows that are completely zero in the matrix
270 
271   Input Parameter:
272 .    A  - the matrix
273 
274   Output Parameter:
275 .    zerorows - the rows that are completely zero
276 
277   Note:
278     zerorows is set to NULL if no rows are zero.
279 
280   Level: intermediate
281 
282 .seealso: `Mat`, `MatFindNonzeroRows()`
283  @*/
284 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows) {
285   IS       keptrows;
286   PetscInt m, n;
287 
288   PetscFunctionBegin;
289   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
290   PetscValidType(mat, 1);
291   PetscValidPointer(zerorows, 2);
292   PetscCall(MatFindNonzeroRows(mat, &keptrows));
293   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
294      In keeping with this convention, we set zerorows to NULL if there are no zero
295      rows. */
296   if (keptrows == NULL) {
297     *zerorows = NULL;
298   } else {
299     PetscCall(MatGetOwnershipRange(mat, &m, &n));
300     PetscCall(ISComplement(keptrows, m, n, zerorows));
301     PetscCall(ISDestroy(&keptrows));
302   }
303   PetscFunctionReturn(0);
304 }
305 
306 /*@
307    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
308 
309    Not Collective
310 
311    Input Parameters:
312 .   A - the matrix
313 
314    Output Parameters:
315 .   a - the diagonal part (which is a SEQUENTIAL matrix)
316 
317    Notes:
318    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
319 
320    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of the containing MPI Mat's normal operation.
321 
322    Level: advanced
323 
324 .seelaso: `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
325 @*/
326 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a) {
327   PetscFunctionBegin;
328   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
329   PetscValidType(A, 1);
330   PetscValidPointer(a, 2);
331   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
332   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
333   else {
334     PetscMPIInt size;
335 
336     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
337     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
338     *a = A;
339   }
340   PetscFunctionReturn(0);
341 }
342 
343 /*@
344    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
345 
346    Collective on mat
347 
348    Input Parameters:
349 .  mat - the matrix
350 
351    Output Parameter:
352 .   trace - the sum of the diagonal entries
353 
354    Level: advanced
355 
356 .seealso: `Mat`
357 @*/
358 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace) {
359   Vec diag;
360 
361   PetscFunctionBegin;
362   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
363   PetscValidScalarPointer(trace, 2);
364   PetscCall(MatCreateVecs(mat, &diag, NULL));
365   PetscCall(MatGetDiagonal(mat, diag));
366   PetscCall(VecSum(diag, trace));
367   PetscCall(VecDestroy(&diag));
368   PetscFunctionReturn(0);
369 }
370 
371 /*@
372    MatRealPart - Zeros out the imaginary part of the matrix
373 
374    Logically Collective on mat
375 
376    Input Parameters:
377 .  mat - the matrix
378 
379    Level: advanced
380 
381 .seealso: `MatImaginaryPart()`
382 @*/
383 PetscErrorCode MatRealPart(Mat mat) {
384   PetscFunctionBegin;
385   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
386   PetscValidType(mat, 1);
387   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
388   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
389   MatCheckPreallocated(mat, 1);
390   PetscUseTypeMethod(mat, realpart);
391   PetscFunctionReturn(0);
392 }
393 
394 /*@C
395    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
396 
397    Collective on mat
398 
399    Input Parameter:
400 .  mat - the matrix
401 
402    Output Parameters:
403 +   nghosts - number of ghosts (note for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
404 -   ghosts - the global indices of the ghost points
405 
406    Note:
407     the nghosts and ghosts are suitable to pass into `VecCreateGhost()`
408 
409    Level: advanced
410 
411 .seealso: `Mat`, `VecCreateGhost()`
412 @*/
413 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[]) {
414   PetscFunctionBegin;
415   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
416   PetscValidType(mat, 1);
417   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
418   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
419   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
420   else {
421     if (nghosts) *nghosts = 0;
422     if (ghosts) *ghosts = NULL;
423   }
424   PetscFunctionReturn(0);
425 }
426 
427 /*@
428    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
429 
430    Logically Collective on mat
431 
432    Input Parameters:
433 .  mat - the matrix
434 
435    Level: advanced
436 
437 .seealso: `MatRealPart()`
438 @*/
439 PetscErrorCode MatImaginaryPart(Mat mat) {
440   PetscFunctionBegin;
441   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
442   PetscValidType(mat, 1);
443   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
444   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
445   MatCheckPreallocated(mat, 1);
446   PetscUseTypeMethod(mat, imaginarypart);
447   PetscFunctionReturn(0);
448 }
449 
450 /*@
451    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
452 
453    Not Collective
454 
455    Input Parameter:
456 .  mat - the matrix
457 
458    Output Parameters:
459 +  missing - is any diagonal missing
460 -  dd - first diagonal entry that is missing (optional) on this process
461 
462    Level: advanced
463 
464 .seealso: `Mat`
465 @*/
466 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd) {
467   PetscFunctionBegin;
468   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
469   PetscValidType(mat, 1);
470   PetscValidBoolPointer(missing, 2);
471   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
472   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
473   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
474   PetscFunctionReturn(0);
475 }
476 
477 /*@C
478    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
479    for each row that you get to ensure that your application does
480    not bleed memory.
481 
482    Not Collective
483 
484    Input Parameters:
485 +  mat - the matrix
486 -  row - the row to get
487 
488    Output Parameters:
489 +  ncols -  if not NULL, the number of nonzeros in the row
490 .  cols - if not NULL, the column numbers
491 -  vals - if not NULL, the values
492 
493    Notes:
494    This routine is provided for people who need to have direct access
495    to the structure of a matrix.  We hope that we provide enough
496    high-level matrix routines that few users will need it.
497 
498    `MatGetRow()` always returns 0-based column indices, regardless of
499    whether the internal representation is 0-based (default) or 1-based.
500 
501    For better efficiency, set cols and/or vals to NULL if you do
502    not wish to extract these quantities.
503 
504    The user can only examine the values extracted with `MatGetRow()`;
505    the values cannot be altered.  To change the matrix entries, one
506    must use `MatSetValues()`.
507 
508    You can only have one call to `MatGetRow()` outstanding for a particular
509    matrix at a time, per processor. `MatGetRow()` can only obtain rows
510    associated with the given processor, it cannot get rows from the
511    other processors; for that we suggest using `MatCreateSubMatrices()`, then
512    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
513    is in the global number of rows.
514 
515    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
516 
517    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
518 
519    Fortran Note:
520    The calling sequence from Fortran is
521 .vb
522    MatGetRow(matrix,row,ncols,cols,values,ierr)
523          Mat     matrix (input)
524          integer row    (input)
525          integer ncols  (output)
526          integer cols(maxcols) (output)
527          double precision (or double complex) values(maxcols) output
528 .ve
529    where maxcols >= maximum nonzeros in any row of the matrix.
530 
531    Caution:
532    Do not try to change the contents of the output arrays (cols and vals).
533    In some cases, this may corrupt the matrix.
534 
535    Level: advanced
536 
537 .seealso: `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
538 @*/
539 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) {
540   PetscInt incols;
541 
542   PetscFunctionBegin;
543   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
544   PetscValidType(mat, 1);
545   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
546   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
547   MatCheckPreallocated(mat, 1);
548   PetscCheck(row >= mat->rmap->rstart && row < mat->rmap->rend, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Only for local rows, %" PetscInt_FMT " not in [%" PetscInt_FMT ",%" PetscInt_FMT ")", row, mat->rmap->rstart, mat->rmap->rend);
549   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
550   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
551   if (ncols) *ncols = incols;
552   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
553   PetscFunctionReturn(0);
554 }
555 
556 /*@
557    MatConjugate - replaces the matrix values with their complex conjugates
558 
559    Logically Collective on mat
560 
561    Input Parameters:
562 .  mat - the matrix
563 
564    Level: advanced
565 
566 .seealso: `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
567 @*/
568 PetscErrorCode MatConjugate(Mat mat) {
569   PetscFunctionBegin;
570   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
571   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
572   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
573     PetscUseTypeMethod(mat, conjugate);
574     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
575   }
576   PetscFunctionReturn(0);
577 }
578 
579 /*@C
580    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
581 
582    Not Collective
583 
584    Input Parameters:
585 +  mat - the matrix
586 .  row - the row to get
587 .  ncols, cols - the number of nonzeros and their columns
588 -  vals - if nonzero the column values
589 
590    Notes:
591    This routine should be called after you have finished examining the entries.
592 
593    This routine zeros out ncols, cols, and vals. This is to prevent accidental
594    us of the array after it has been restored. If you pass NULL, it will
595    not zero the pointers.  Use of cols or vals after `MatRestoreRow()` is invalid.
596 
597    Fortran Notes:
598    The calling sequence from Fortran is
599 .vb
600    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
601       Mat     matrix (input)
602       integer row    (input)
603       integer ncols  (output)
604       integer cols(maxcols) (output)
605       double precision (or double complex) values(maxcols) output
606 .ve
607    Where maxcols >= maximum nonzeros in any row of the matrix.
608 
609    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
610    before another call to `MatGetRow()` can be made.
611 
612    Level: advanced
613 
614 .seealso: `MatGetRow()`
615 @*/
616 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[]) {
617   PetscFunctionBegin;
618   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
619   if (ncols) PetscValidIntPointer(ncols, 3);
620   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
621   if (!mat->ops->restorerow) PetscFunctionReturn(0);
622   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
623   if (ncols) *ncols = 0;
624   if (cols) *cols = NULL;
625   if (vals) *vals = NULL;
626   PetscFunctionReturn(0);
627 }
628 
629 /*@
630    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
631    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
632 
633    Not Collective
634 
635    Input Parameters:
636 .  mat - the matrix
637 
638    Note:
639    The flag is to ensure that users are aware that `MatGetRow()` only provides the upper triangular part of the row for the matrices in `MATSBAIJ` format.
640 
641    Level: advanced
642 
643 .seealso: `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
644 @*/
645 PetscErrorCode MatGetRowUpperTriangular(Mat mat) {
646   PetscFunctionBegin;
647   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
648   PetscValidType(mat, 1);
649   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
650   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
651   MatCheckPreallocated(mat, 1);
652   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(0);
653   PetscUseTypeMethod(mat, getrowuppertriangular);
654   PetscFunctionReturn(0);
655 }
656 
657 /*@
658    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
659 
660    Not Collective
661 
662    Input Parameters:
663 .  mat - the matrix
664 
665    Note:
666    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
667 
668    Level: advanced
669 
670 .seealso: `MATSBAIJ`, `MatGetRowUpperTriangular()`
671 @*/
672 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat) {
673   PetscFunctionBegin;
674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
675   PetscValidType(mat, 1);
676   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
677   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
678   MatCheckPreallocated(mat, 1);
679   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(0);
680   PetscUseTypeMethod(mat, restorerowuppertriangular);
681   PetscFunctionReturn(0);
682 }
683 
684 /*@C
685    MatSetOptionsPrefix - Sets the prefix used for searching for all
686    `Mat` options in the database.
687 
688    Logically Collective on A
689 
690    Input Parameters:
691 +  A - the matrix
692 -  prefix - the prefix to prepend to all option names
693 
694    Notes:
695    A hyphen (-) must NOT be given at the beginning of the prefix name.
696    The first character of all runtime options is AUTOMATICALLY the hyphen.
697 
698    This is NOT used for options for the factorization of the matrix. Normally the
699    prefix is automatically passed in from the PC calling the factorization. To set
700    it directly use  `MatSetOptionsPrefixFactor()`
701 
702    Level: advanced
703 
704 .seealso: `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
705 @*/
706 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[]) {
707   PetscFunctionBegin;
708   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
709   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
710   PetscFunctionReturn(0);
711 }
712 
713 /*@C
714    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
715    for matrices created with `MatGetFactor()`
716 
717    Logically Collective on A
718 
719    Input Parameters:
720 +  A - the matrix
721 -  prefix - the prefix to prepend to all option names for the factored matrix
722 
723    Notes:
724    A hyphen (-) must NOT be given at the beginning of the prefix name.
725    The first character of all runtime options is AUTOMATICALLY the hyphen.
726 
727    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
728    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
729 
730    Level: developer
731 
732 .seealso:   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
733 @*/
734 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[]) {
735   PetscFunctionBegin;
736   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
737   if (prefix) {
738     PetscValidCharPointer(prefix, 2);
739     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
740     if (prefix != A->factorprefix) {
741       PetscCall(PetscFree(A->factorprefix));
742       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
743     }
744   } else PetscCall(PetscFree(A->factorprefix));
745   PetscFunctionReturn(0);
746 }
747 
748 /*@C
749    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
750    for matrices created with `MatGetFactor()`
751 
752    Logically Collective on A
753 
754    Input Parameters:
755 +  A - the matrix
756 -  prefix - the prefix to prepend to all option names for the factored matrix
757 
758    Notes:
759    A hyphen (-) must NOT be given at the beginning of the prefix name.
760    The first character of all runtime options is AUTOMATICALLY the hyphen.
761 
762    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
763    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
764 
765    Level: developer
766 
767 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
768           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
769           `MatSetOptionsPrefix()`
770 @*/
771 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[]) {
772   char  *buf = A->factorprefix;
773   size_t len1, len2;
774 
775   PetscFunctionBegin;
776   PetscValidHeader(A, 1);
777   if (!prefix) PetscFunctionReturn(0);
778   if (!buf) {
779     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
780     PetscFunctionReturn(0);
781   }
782   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
783 
784   PetscCall(PetscStrlen(prefix, &len1));
785   PetscCall(PetscStrlen(buf, &len2));
786   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
787   PetscCall(PetscStrcpy(A->factorprefix, buf));
788   PetscCall(PetscStrcat(A->factorprefix, prefix));
789   PetscCall(PetscFree(buf));
790   PetscFunctionReturn(0);
791 }
792 
793 /*@C
794    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
795    matrix options in the database.
796 
797    Logically Collective on A
798 
799    Input Parameters:
800 +  A - the matrix
801 -  prefix - the prefix to prepend to all option names
802 
803    Note:
804    A hyphen (-) must NOT be given at the beginning of the prefix name.
805    The first character of all runtime options is AUTOMATICALLY the hyphen.
806 
807    Level: advanced
808 
809 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
810 @*/
811 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[]) {
812   PetscFunctionBegin;
813   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
814   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
815   PetscFunctionReturn(0);
816 }
817 
818 /*@C
819    MatGetOptionsPrefix - Gets the prefix used for searching for all
820    matrix options in the database.
821 
822    Not Collective
823 
824    Input Parameter:
825 .  A - the matrix
826 
827    Output Parameter:
828 .  prefix - pointer to the prefix string used
829 
830    Fortran Note:
831     On the fortran side, the user should pass in a string 'prefix' of
832    sufficient length to hold the prefix.
833 
834    Level: advanced
835 
836 .seealso: `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
837 @*/
838 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[]) {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscValidPointer(prefix, 2);
842   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
843   PetscFunctionReturn(0);
844 }
845 
846 /*@
847    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
848 
849    Collective on A
850 
851    Input Parameters:
852 .  A - the matrix
853 
854    Notes:
855    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
856 
857    Users can reset the preallocation to access the original memory.
858 
859    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.
860 
861    Level: beginner
862 
863 .seealso: `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
864 @*/
865 PetscErrorCode MatResetPreallocation(Mat A) {
866   PetscFunctionBegin;
867   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
868   PetscValidType(A, 1);
869   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
870   PetscFunctionReturn(0);
871 }
872 
873 /*@
874    MatSetUp - Sets up the internal matrix data structures for later use.
875 
876    Collective on A
877 
878    Input Parameters:
879 .  A - the matrix
880 
881    Notes:
882    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
883 
884    If a suitable preallocation routine is used, this function does not need to be called.
885 
886    See the Performance chapter of the PETSc users manual for how to preallocate matrices
887 
888    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
889 
890    Level: intermediate
891 
892 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
893 @*/
894 PetscErrorCode MatSetUp(Mat A) {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   if (!((PetscObject)A)->type_name) {
898     PetscMPIInt size;
899 
900     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
901     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
902   }
903   if (!A->preallocated && A->ops->setup) {
904     PetscCall(PetscInfo(A, "Warning not preallocating matrix storage\n"));
905     PetscUseTypeMethod(A, setup);
906   }
907   PetscCall(PetscLayoutSetUp(A->rmap));
908   PetscCall(PetscLayoutSetUp(A->cmap));
909   A->preallocated = PETSC_TRUE;
910   PetscFunctionReturn(0);
911 }
912 
913 #if defined(PETSC_HAVE_SAWS)
914 #include <petscviewersaws.h>
915 #endif
916 
917 /*@C
918    MatViewFromOptions - View properties of the matrix from the options database
919 
920    Collective on A
921 
922    Input Parameters:
923 +  A - the matrix
924 .  obj - optional additional object that provides the options prefix to use
925 -  name - command line option
926 
927   Options Database:
928 .  -mat_view [viewertype]:... - the viewer and its options
929 
930   Notes:
931 .vb
932     If no value is provided ascii:stdout is used
933        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
934                                                   for example ascii::ascii_info prints just the information about the object not all details
935                                                   unless :append is given filename opens in write mode, overwriting what was already there
936        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
937        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
938        socket[:port]                             defaults to the standard output port
939        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
940 .ve
941 
942    Level: intermediate
943 
944 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
945 @*/
946 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[]) {
947   PetscFunctionBegin;
948   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
949   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
950   PetscFunctionReturn(0);
951 }
952 
953 /*@C
954    MatView - display information about a matrix in a variety ways
955 
956    Collective on mat
957 
958    Input Parameters:
959 +  mat - the matrix
960 -  viewer - visualization context
961 
962   Notes:
963   The available visualization contexts include
964 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
965 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
966 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
967 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
968 
969    The user can open alternative visualization contexts with
970 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
971 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
972          specified file; corresponding input uses MatLoad()
973 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
974          an X window display
975 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
976          Currently only the sequential dense and AIJ
977          matrix types support the Socket viewer.
978 
979    The user can call `PetscViewerPushFormat()` to specify the output
980    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
981    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
982 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
983 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
984 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
985 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
986          format common among all matrix types
987 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
988          format (which is in many cases the same as the default)
989 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
990          size and structure (not the matrix entries)
991 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
992          the matrix structure
993 
994    Options Database Keys:
995 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
996 .  -mat_view ::ascii_info_detail - Prints more detailed info
997 .  -mat_view - Prints matrix in ASCII format
998 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
999 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1000 .  -display <name> - Sets display name (default is host)
1001 .  -draw_pause <sec> - Sets number of seconds to pause after display
1002 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1003 .  -viewer_socket_machine <machine> -
1004 .  -viewer_socket_port <port> -
1005 .  -mat_view binary - save matrix to file in binary format
1006 -  -viewer_binary_filename <name> -
1007 
1008    Level: beginner
1009 
1010    Notes:
1011     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1012     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1013 
1014     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1015 
1016     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1017       viewer is used.
1018 
1019       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1020       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1021 
1022       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1023       and then use the following mouse functions.
1024 .vb
1025   left mouse: zoom in
1026   middle mouse: zoom out
1027   right mouse: continue with the simulation
1028 .ve
1029 
1030 .seealso: `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`, `Mat`,
1031           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1032 @*/
1033 PetscErrorCode MatView(Mat mat, PetscViewer viewer) {
1034   PetscInt          rows, cols, rbs, cbs;
1035   PetscBool         isascii, isstring, issaws;
1036   PetscViewerFormat format;
1037   PetscMPIInt       size;
1038 
1039   PetscFunctionBegin;
1040   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1041   PetscValidType(mat, 1);
1042   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1043   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1044   PetscCheckSameComm(mat, 1, viewer, 2);
1045   MatCheckPreallocated(mat, 1);
1046 
1047   PetscCall(PetscViewerGetFormat(viewer, &format));
1048   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1049   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(0);
1050 
1051   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1052   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1053   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1054   PetscCheck((isascii && (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL)) || !mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "No viewers for factored matrix except ASCII, info, or info_detail");
1055 
1056   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1057   if (isascii) {
1058     PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ORDER, "Must call MatAssemblyBegin/End() before viewing matrix");
1059     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1060     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1061       MatNullSpace nullsp, transnullsp;
1062 
1063       PetscCall(PetscViewerASCIIPushTab(viewer));
1064       PetscCall(MatGetSize(mat, &rows, &cols));
1065       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1066       if (rbs != 1 || cbs != 1) {
1067         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1068         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1069       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1070       if (mat->factortype) {
1071         MatSolverType solver;
1072         PetscCall(MatFactorGetSolverType(mat, &solver));
1073         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1074       }
1075       if (mat->ops->getinfo) {
1076         MatInfo info;
1077         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1078         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1079         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1080       }
1081       PetscCall(MatGetNullSpace(mat, &nullsp));
1082       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1083       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1084       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1085       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1086       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1087       PetscCall(PetscViewerASCIIPushTab(viewer));
1088       PetscCall(MatProductView(mat, viewer));
1089       PetscCall(PetscViewerASCIIPopTab(viewer));
1090     }
1091   } else if (issaws) {
1092 #if defined(PETSC_HAVE_SAWS)
1093     PetscMPIInt rank;
1094 
1095     PetscCall(PetscObjectName((PetscObject)mat));
1096     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1097     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1098 #endif
1099   } else if (isstring) {
1100     const char *type;
1101     PetscCall(MatGetType(mat, &type));
1102     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1103     PetscTryTypeMethod(mat, view, viewer);
1104   }
1105   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1106     PetscCall(PetscViewerASCIIPushTab(viewer));
1107     PetscUseTypeMethod(mat, viewnative, viewer);
1108     PetscCall(PetscViewerASCIIPopTab(viewer));
1109   } else if (mat->ops->view) {
1110     PetscCall(PetscViewerASCIIPushTab(viewer));
1111     PetscUseTypeMethod(mat, view, viewer);
1112     PetscCall(PetscViewerASCIIPopTab(viewer));
1113   }
1114   if (isascii) {
1115     PetscCall(PetscViewerGetFormat(viewer, &format));
1116     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1117   }
1118   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1119   PetscFunctionReturn(0);
1120 }
1121 
1122 #if defined(PETSC_USE_DEBUG)
1123 #include <../src/sys/totalview/tv_data_display.h>
1124 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat) {
1125   TV_add_row("Local rows", "int", &mat->rmap->n);
1126   TV_add_row("Local columns", "int", &mat->cmap->n);
1127   TV_add_row("Global rows", "int", &mat->rmap->N);
1128   TV_add_row("Global columns", "int", &mat->cmap->N);
1129   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1130   return TV_format_OK;
1131 }
1132 #endif
1133 
1134 /*@C
1135    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1136    with `MatView()`.  The matrix format is determined from the options database.
1137    Generates a parallel MPI matrix if the communicator has more than one
1138    processor.  The default matrix type is `MATAIJ`.
1139 
1140    Collective on mat
1141 
1142    Input Parameters:
1143 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1144             or some related function before a call to `MatLoad()`
1145 -  viewer - binary/HDF5 file viewer
1146 
1147    Options Database Keys:
1148    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1149    block size
1150 .    -matload_block_size <bs> - set block size
1151 
1152    Level: beginner
1153 
1154    Notes:
1155    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1156    `Mat` before calling this routine if you wish to set it from the options database.
1157 
1158    `MatLoad()` automatically loads into the options database any options
1159    given in the file filename.info where filename is the name of the file
1160    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1161    file will be ignored if you use the -viewer_binary_skip_info option.
1162 
1163    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1164    sets the default matrix type AIJ and sets the local and global sizes.
1165    If type and/or size is already set, then the same are used.
1166 
1167    In parallel, each processor can load a subset of rows (or the
1168    entire matrix).  This routine is especially useful when a large
1169    matrix is stored on disk and only part of it is desired on each
1170    processor.  For example, a parallel solver may access only some of
1171    the rows from each processor.  The algorithm used here reads
1172    relatively small blocks of data rather than reading the entire
1173    matrix and then subsetting it.
1174 
1175    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1176    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1177    or the sequence like
1178 .vb
1179     `PetscViewer` v;
1180     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1181     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1182     `PetscViewerSetFromOptions`(v);
1183     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1184     `PetscViewerFileSetName`(v,"datafile");
1185 .ve
1186    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1187 $ -viewer_type {binary,hdf5}
1188 
1189    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1190    and src/mat/tutorials/ex10.c with the second approach.
1191 
1192    Notes about the PETSc binary format:
1193    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1194    is read onto rank 0 and then shipped to its destination rank, one after another.
1195    Multiple objects, both matrices and vectors, can be stored within the same file.
1196    Their PetscObject name is ignored; they are loaded in the order of their storage.
1197 
1198    Most users should not need to know the details of the binary storage
1199    format, since `MatLoad()` and `MatView()` completely hide these details.
1200    But for anyone who's interested, the standard binary matrix storage
1201    format is
1202 
1203 $    PetscInt    MAT_FILE_CLASSID
1204 $    PetscInt    number of rows
1205 $    PetscInt    number of columns
1206 $    PetscInt    total number of nonzeros
1207 $    PetscInt    *number nonzeros in each row
1208 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1209 $    PetscScalar *values of all nonzeros
1210 
1211    PETSc automatically does the byte swapping for
1212 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1213 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1214 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1215 and `PetscBinaryWrite()` to see how this may be done.
1216 
1217    Notes about the HDF5 (MATLAB MAT-File Version 7.3) format:
1218    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1219    Each processor's chunk is loaded independently by its owning rank.
1220    Multiple objects, both matrices and vectors, can be stored within the same file.
1221    They are looked up by their PetscObject name.
1222 
1223    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1224    by default the same structure and naming of the AIJ arrays and column count
1225    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1226 $    save example.mat A b -v7.3
1227    can be directly read by this routine (see Reference 1 for details).
1228    Note that depending on your MATLAB version, this format might be a default,
1229    otherwise you can set it as default in Preferences.
1230 
1231    Unless -nocompression flag is used to save the file in MATLAB,
1232    PETSc must be configured with ZLIB package.
1233 
1234    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1235 
1236    Current HDF5 (MAT-File) limitations:
1237    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices.
1238 
1239    Corresponding `MatView()` is not yet implemented.
1240 
1241    The loaded matrix is actually a transpose of the original one in MATLAB,
1242    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1243    With this format, matrix is automatically transposed by PETSc,
1244    unless the matrix is marked as SPD or symmetric
1245    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1246 
1247    References:
1248 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1249 
1250 .seealso: `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1251  @*/
1252 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer) {
1253   PetscBool flg;
1254 
1255   PetscFunctionBegin;
1256   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1257   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1258 
1259   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1260 
1261   flg = PETSC_FALSE;
1262   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1263   if (flg) {
1264     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1265     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1266   }
1267   flg = PETSC_FALSE;
1268   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1269   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1270 
1271   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1272   PetscUseTypeMethod(mat, load, viewer);
1273   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1274   PetscFunctionReturn(0);
1275 }
1276 
1277 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant) {
1278   Mat_Redundant *redund = *redundant;
1279 
1280   PetscFunctionBegin;
1281   if (redund) {
1282     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1283       PetscCall(ISDestroy(&redund->isrow));
1284       PetscCall(ISDestroy(&redund->iscol));
1285       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1286     } else {
1287       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1288       PetscCall(PetscFree(redund->sbuf_j));
1289       PetscCall(PetscFree(redund->sbuf_a));
1290       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1291         PetscCall(PetscFree(redund->rbuf_j[i]));
1292         PetscCall(PetscFree(redund->rbuf_a[i]));
1293       }
1294       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1295     }
1296 
1297     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1298     PetscCall(PetscFree(redund));
1299   }
1300   PetscFunctionReturn(0);
1301 }
1302 
1303 /*@C
1304    MatDestroy - Frees space taken by a matrix.
1305 
1306    Collective on A
1307 
1308    Input Parameter:
1309 .  A - the matrix
1310 
1311    Level: beginner
1312 
1313    Developer Note:
1314    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1315    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1316    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1317    if changes are needed here.
1318 
1319 .seealso: `Mat`, `MatCreate()`
1320 @*/
1321 PetscErrorCode MatDestroy(Mat *A) {
1322   PetscFunctionBegin;
1323   if (!*A) PetscFunctionReturn(0);
1324   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1325   if (--((PetscObject)(*A))->refct > 0) {
1326     *A = NULL;
1327     PetscFunctionReturn(0);
1328   }
1329 
1330   /* if memory was published with SAWs then destroy it */
1331   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1332   PetscTryTypeMethod((*A), destroy);
1333 
1334   PetscCall(PetscFree((*A)->factorprefix));
1335   PetscCall(PetscFree((*A)->defaultvectype));
1336   PetscCall(PetscFree((*A)->defaultrandtype));
1337   PetscCall(PetscFree((*A)->bsizes));
1338   PetscCall(PetscFree((*A)->solvertype));
1339   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1340   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1341   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1342   PetscCall(MatProductClear(*A));
1343   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1344   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1345   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1346   PetscCall(MatDestroy(&(*A)->schur));
1347   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1348   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1349   PetscCall(PetscHeaderDestroy(A));
1350   PetscFunctionReturn(0);
1351 }
1352 
1353 /*@C
1354    MatSetValues - Inserts or adds a block of values into a matrix.
1355    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1356    MUST be called after all calls to `MatSetValues()` have been completed.
1357 
1358    Not Collective
1359 
1360    Input Parameters:
1361 +  mat - the matrix
1362 .  v - a logically two-dimensional array of values
1363 .  m, idxm - the number of rows and their global indices
1364 .  n, idxn - the number of columns and their global indices
1365 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1366 
1367    Notes:
1368    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1369       `MatSetUp()` before using this routine
1370 
1371    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1372 
1373    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1374    options cannot be mixed without intervening calls to the assembly
1375    routines.
1376 
1377    `MatSetValues()` uses 0-based row and column numbers in Fortran
1378    as well as in C.
1379 
1380    Negative indices may be passed in idxm and idxn, these rows and columns are
1381    simply ignored. This allows easily inserting element stiffness matrices
1382    with homogeneous Dirchlet boundary conditions that you don't want represented
1383    in the matrix.
1384 
1385    Efficiency Alert:
1386    The routine `MatSetValuesBlocked()` may offer much better efficiency
1387    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1388 
1389    Level: beginner
1390 
1391    Developer Note:
1392    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1393    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1394 
1395 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1396           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1397 @*/
1398 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) {
1399   PetscFunctionBeginHot;
1400   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1401   PetscValidType(mat, 1);
1402   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1403   PetscValidIntPointer(idxm, 3);
1404   PetscValidIntPointer(idxn, 5);
1405   MatCheckPreallocated(mat, 1);
1406 
1407   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1408   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1409 
1410   if (PetscDefined(USE_DEBUG)) {
1411     PetscInt i, j;
1412 
1413     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1414     for (i = 0; i < m; i++) {
1415       for (j = 0; j < n; j++) {
1416         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1417 #if defined(PETSC_USE_COMPLEX)
1418           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g+i%g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)PetscRealPart(v[i * n + j]), (double)PetscImaginaryPart(v[i * n + j]), idxm[i], idxn[j]);
1419 #else
1420           SETERRQ(PETSC_COMM_SELF, PETSC_ERR_FP, "Inserting %g at matrix entry (%" PetscInt_FMT ",%" PetscInt_FMT ")", (double)v[i * n + j], idxm[i], idxn[j]);
1421 #endif
1422       }
1423     }
1424     for (i = 0; i < m; i++) PetscCheck(idxm[i] < mat->rmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in row %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxm[i], mat->rmap->N - 1);
1425     for (i = 0; i < n; i++) PetscCheck(idxn[i] < mat->cmap->N, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot insert in column %" PetscInt_FMT ", maximum is %" PetscInt_FMT, idxn[i], mat->cmap->N - 1);
1426   }
1427 
1428   if (mat->assembled) {
1429     mat->was_assembled = PETSC_TRUE;
1430     mat->assembled     = PETSC_FALSE;
1431   }
1432   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1433   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1434   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1435   PetscFunctionReturn(0);
1436 }
1437 
1438 /*@C
1439    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1440    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1441    MUST be called after all calls to `MatSetValues()` have been completed.
1442 
1443    Not Collective
1444 
1445    Input Parameters:
1446 +  mat - the matrix
1447 .  v - a logically two-dimensional array of values
1448 .  ism - the rows to provide
1449 .  isn - the columns to provide
1450 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1451 
1452    Notes:
1453    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1454       `MatSetUp()` before using this routine
1455 
1456    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1457 
1458    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1459    options cannot be mixed without intervening calls to the assembly
1460    routines.
1461 
1462    MatSetValues() uses 0-based row and column numbers in Fortran
1463    as well as in C.
1464 
1465    Negative indices may be passed in ism and isn, these rows and columns are
1466    simply ignored. This allows easily inserting element stiffness matrices
1467    with homogeneous Dirchlet boundary conditions that you don't want represented
1468    in the matrix.
1469 
1470    Efficiency Alert:
1471    The routine `MatSetValuesBlocked()` may offer much better efficiency
1472    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1473 
1474    Level: beginner
1475 
1476    Developer Notes:
1477     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1478                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1479 
1480     This is currently not optimized for any particular `ISType`
1481 
1482 .seealso: `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1483           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1484 @*/
1485 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv) {
1486   PetscInt        m, n;
1487   const PetscInt *rows, *cols;
1488 
1489   PetscFunctionBeginHot;
1490   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1491   PetscCall(ISGetIndices(ism, &rows));
1492   PetscCall(ISGetIndices(isn, &cols));
1493   PetscCall(ISGetLocalSize(ism, &m));
1494   PetscCall(ISGetLocalSize(isn, &n));
1495   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1496   PetscCall(ISRestoreIndices(ism, &rows));
1497   PetscCall(ISRestoreIndices(isn, &cols));
1498   PetscFunctionReturn(0);
1499 }
1500 
1501 /*@
1502    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1503         values into a matrix
1504 
1505    Not Collective
1506 
1507    Input Parameters:
1508 +  mat - the matrix
1509 .  row - the (block) row to set
1510 -  v - a logically two-dimensional array of values
1511 
1512    Notes:
1513    By the values, v, are column-oriented (for the block version) and sorted
1514 
1515    All the nonzeros in the row must be provided
1516 
1517    The matrix must have previously had its column indices set
1518 
1519    The row must belong to this process
1520 
1521    Level: intermediate
1522 
1523 .seealso: `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1524           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1525 @*/
1526 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[]) {
1527   PetscInt globalrow;
1528 
1529   PetscFunctionBegin;
1530   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1531   PetscValidType(mat, 1);
1532   PetscValidScalarPointer(v, 3);
1533   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1534   PetscCall(MatSetValuesRow(mat, globalrow, v));
1535   PetscFunctionReturn(0);
1536 }
1537 
1538 /*@
1539    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1540         values into a matrix
1541 
1542    Not Collective
1543 
1544    Input Parameters:
1545 +  mat - the matrix
1546 .  row - the (block) row to set
1547 -  v - a logically two-dimensional (column major) array of values for  block matrices with blocksize larger than one, otherwise a one dimensional array of values
1548 
1549    Notes:
1550    The values, v, are column-oriented for the block version.
1551 
1552    All the nonzeros in the row must be provided
1553 
1554    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1555 
1556    The row must belong to this process
1557 
1558    Level: advanced
1559 
1560 .seealso: `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1561           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1562 @*/
1563 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[]) {
1564   PetscFunctionBeginHot;
1565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1566   PetscValidType(mat, 1);
1567   MatCheckPreallocated(mat, 1);
1568   PetscValidScalarPointer(v, 3);
1569   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1570   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1571   mat->insertmode = INSERT_VALUES;
1572 
1573   if (mat->assembled) {
1574     mat->was_assembled = PETSC_TRUE;
1575     mat->assembled     = PETSC_FALSE;
1576   }
1577   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1578   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1579   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1580   PetscFunctionReturn(0);
1581 }
1582 
1583 /*@
1584    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1585      Using structured grid indexing
1586 
1587    Not Collective
1588 
1589    Input Parameters:
1590 +  mat - the matrix
1591 .  m - number of rows being entered
1592 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1593 .  n - number of columns being entered
1594 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1595 .  v - a logically two-dimensional array of values
1596 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1597 
1598    Notes:
1599    By default the values, v, are row-oriented.  See `MatSetOption()` for other options.
1600 
1601    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1602    options cannot be mixed without intervening calls to the assembly
1603    routines.
1604 
1605    The grid coordinates are across the entire grid, not just the local portion
1606 
1607    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1608    as well as in C.
1609 
1610    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1611 
1612    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1613    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1614 
1615    The columns and rows in the stencil passed in MUST be contained within the
1616    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1617    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1618    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1619    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1620 
1621    In Fortran idxm and idxn should be declared as
1622 $     MatStencil idxm(4,m),idxn(4,n)
1623    and the values inserted using
1624 $    idxm(MatStencil_i,1) = i
1625 $    idxm(MatStencil_j,1) = j
1626 $    idxm(MatStencil_k,1) = k
1627 $    idxm(MatStencil_c,1) = c
1628    etc
1629 
1630    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1631    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1632    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1633    `DM_BOUNDARY_PERIODIC` boundary type.
1634 
1635    For indices that don't mean anything for your case (like the k index when working in 2d) or the c index when you have
1636    a single value per point) you can skip filling those indices.
1637 
1638    Inspired by the structured grid interface to the HYPRE package
1639    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1640 
1641    Efficiency Alert:
1642    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1643    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1644 
1645    Level: beginner
1646 
1647 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1648           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1649 @*/
1650 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) {
1651   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1652   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1653   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1654 
1655   PetscFunctionBegin;
1656   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1657   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1658   PetscValidType(mat, 1);
1659   PetscValidPointer(idxm, 3);
1660   PetscValidPointer(idxn, 5);
1661 
1662   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1663     jdxm = buf;
1664     jdxn = buf + m;
1665   } else {
1666     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1667     jdxm = bufm;
1668     jdxn = bufn;
1669   }
1670   for (i = 0; i < m; i++) {
1671     for (j = 0; j < 3 - sdim; j++) dxm++;
1672     tmp = *dxm++ - starts[0];
1673     for (j = 0; j < dim - 1; j++) {
1674       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1675       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1676     }
1677     if (mat->stencil.noc) dxm++;
1678     jdxm[i] = tmp;
1679   }
1680   for (i = 0; i < n; i++) {
1681     for (j = 0; j < 3 - sdim; j++) dxn++;
1682     tmp = *dxn++ - starts[0];
1683     for (j = 0; j < dim - 1; j++) {
1684       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1685       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1686     }
1687     if (mat->stencil.noc) dxn++;
1688     jdxn[i] = tmp;
1689   }
1690   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1691   PetscCall(PetscFree2(bufm, bufn));
1692   PetscFunctionReturn(0);
1693 }
1694 
1695 /*@
1696    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1697      Using structured grid indexing
1698 
1699    Not Collective
1700 
1701    Input Parameters:
1702 +  mat - the matrix
1703 .  m - number of rows being entered
1704 .  idxm - grid coordinates for matrix rows being entered
1705 .  n - number of columns being entered
1706 .  idxn - grid coordinates for matrix columns being entered
1707 .  v - a logically two-dimensional array of values
1708 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1709 
1710    Notes:
1711    By default the values, v, are row-oriented and unsorted.
1712    See `MatSetOption()` for other options.
1713 
1714    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1715    options cannot be mixed without intervening calls to the assembly
1716    routines.
1717 
1718    The grid coordinates are across the entire grid, not just the local portion
1719 
1720    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1721    as well as in C.
1722 
1723    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1724 
1725    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1726    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1727 
1728    The columns and rows in the stencil passed in MUST be contained within the
1729    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1730    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1731    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1732    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1733 
1734    In Fortran idxm and idxn should be declared as
1735 $     MatStencil idxm(4,m),idxn(4,n)
1736    and the values inserted using
1737 $    idxm(MatStencil_i,1) = i
1738 $    idxm(MatStencil_j,1) = j
1739 $    idxm(MatStencil_k,1) = k
1740    etc
1741 
1742    Negative indices may be passed in idxm and idxn, these rows and columns are
1743    simply ignored. This allows easily inserting element stiffness matrices
1744    with homogeneous Dirchlet boundary conditions that you don't want represented
1745    in the matrix.
1746 
1747    Inspired by the structured grid interface to the HYPRE package
1748    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1749 
1750    Level: beginner
1751 
1752 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1753           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1754           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1755 @*/
1756 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv) {
1757   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1758   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1759   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1760 
1761   PetscFunctionBegin;
1762   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1763   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1764   PetscValidType(mat, 1);
1765   PetscValidPointer(idxm, 3);
1766   PetscValidPointer(idxn, 5);
1767   PetscValidScalarPointer(v, 6);
1768 
1769   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1770     jdxm = buf;
1771     jdxn = buf + m;
1772   } else {
1773     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1774     jdxm = bufm;
1775     jdxn = bufn;
1776   }
1777   for (i = 0; i < m; i++) {
1778     for (j = 0; j < 3 - sdim; j++) dxm++;
1779     tmp = *dxm++ - starts[0];
1780     for (j = 0; j < sdim - 1; j++) {
1781       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1782       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1783     }
1784     dxm++;
1785     jdxm[i] = tmp;
1786   }
1787   for (i = 0; i < n; i++) {
1788     for (j = 0; j < 3 - sdim; j++) dxn++;
1789     tmp = *dxn++ - starts[0];
1790     for (j = 0; j < sdim - 1; j++) {
1791       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1792       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1793     }
1794     dxn++;
1795     jdxn[i] = tmp;
1796   }
1797   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1798   PetscCall(PetscFree2(bufm, bufn));
1799   PetscFunctionReturn(0);
1800 }
1801 
1802 /*@
1803    MatSetStencil - Sets the grid information for setting values into a matrix via
1804         `MatSetValuesStencil()`
1805 
1806    Not Collective
1807 
1808    Input Parameters:
1809 +  mat - the matrix
1810 .  dim - dimension of the grid 1, 2, or 3
1811 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1812 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1813 -  dof - number of degrees of freedom per node
1814 
1815    Notes:
1816    Inspired by the structured grid interface to the HYPRE package
1817    (www.llnl.gov/CASC/hyper)
1818 
1819    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1820    user.
1821 
1822    Level: beginner
1823 
1824 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1825           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1826 @*/
1827 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof) {
1828   PetscFunctionBegin;
1829   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1830   PetscValidIntPointer(dims, 3);
1831   PetscValidIntPointer(starts, 4);
1832 
1833   mat->stencil.dim = dim + (dof > 1);
1834   for (PetscInt i = 0; i < dim; i++) {
1835     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1836     mat->stencil.starts[i] = starts[dim - i - 1];
1837   }
1838   mat->stencil.dims[dim]   = dof;
1839   mat->stencil.starts[dim] = 0;
1840   mat->stencil.noc         = (PetscBool)(dof == 1);
1841   PetscFunctionReturn(0);
1842 }
1843 
1844 /*@C
1845    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1846 
1847    Not Collective
1848 
1849    Input Parameters:
1850 +  mat - the matrix
1851 .  v - a logically two-dimensional array of values
1852 .  m, idxm - the number of block rows and their global block indices
1853 .  n, idxn - the number of block columns and their global block indices
1854 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1855 
1856    Notes:
1857    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1858    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1859 
1860    The m and n count the NUMBER of blocks in the row direction and column direction,
1861    NOT the total number of rows/columns; for example, if the block size is 2 and
1862    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1863    The values in idxm would be 1 2; that is the first index for each block divided by
1864    the block size.
1865 
1866    Note that you must call `MatSetBlockSize()` when constructing this matrix (before
1867    preallocating it).
1868 
1869    By default the values, v, are row-oriented, so the layout of
1870    v is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1871 
1872    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1873    options cannot be mixed without intervening calls to the assembly
1874    routines.
1875 
1876    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1877    as well as in C.
1878 
1879    Negative indices may be passed in idxm and idxn, these rows and columns are
1880    simply ignored. This allows easily inserting element stiffness matrices
1881    with homogeneous Dirchlet boundary conditions that you don't want represented
1882    in the matrix.
1883 
1884    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1885    internal searching must be done to determine where to place the
1886    data in the matrix storage space.  By instead inserting blocks of
1887    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1888    reduced.
1889 
1890    Example:
1891 $   Suppose m=n=2 and block size(bs) = 2 The array is
1892 $
1893 $   1  2  | 3  4
1894 $   5  6  | 7  8
1895 $   - - - | - - -
1896 $   9  10 | 11 12
1897 $   13 14 | 15 16
1898 $
1899 $   v[] should be passed in like
1900 $   v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1901 $
1902 $  If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1903 $   v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1904 
1905    Level: intermediate
1906 
1907 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1908 @*/
1909 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv) {
1910   PetscFunctionBeginHot;
1911   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1912   PetscValidType(mat, 1);
1913   if (!m || !n) PetscFunctionReturn(0); /* no values to insert */
1914   PetscValidIntPointer(idxm, 3);
1915   PetscValidIntPointer(idxn, 5);
1916   MatCheckPreallocated(mat, 1);
1917   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1918   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1919   if (PetscDefined(USE_DEBUG)) {
1920     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1921     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1922   }
1923   if (PetscDefined(USE_DEBUG)) {
1924     PetscInt rbs, cbs, M, N, i;
1925     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1926     PetscCall(MatGetSize(mat, &M, &N));
1927     for (i = 0; i < m; i++) PetscCheck(idxm[i] * rbs < M, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Row block index %" PetscInt_FMT " (index %" PetscInt_FMT ") greater than row length %" PetscInt_FMT, i, idxm[i], M);
1928     for (i = 0; i < n; i++) PetscCheck(idxn[i] * cbs < N, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Column block index %" PetscInt_FMT " (index %" PetscInt_FMT ") great than column length %" PetscInt_FMT, i, idxn[i], N);
1929   }
1930   if (mat->assembled) {
1931     mat->was_assembled = PETSC_TRUE;
1932     mat->assembled     = PETSC_FALSE;
1933   }
1934   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1935   if (mat->ops->setvaluesblocked) {
1936     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1937   } else {
1938     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1939     PetscInt i, j, bs, cbs;
1940 
1941     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1942     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1943       iidxm = buf;
1944       iidxn = buf + m * bs;
1945     } else {
1946       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1947       iidxm = bufr;
1948       iidxn = bufc;
1949     }
1950     for (i = 0; i < m; i++) {
1951       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
1952     }
1953     if (m != n || bs != cbs || idxm != idxn) {
1954       for (i = 0; i < n; i++) {
1955         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
1956       }
1957     } else iidxn = iidxm;
1958     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
1959     PetscCall(PetscFree2(bufr, bufc));
1960   }
1961   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1962   PetscFunctionReturn(0);
1963 }
1964 
1965 /*@C
1966    MatGetValues - Gets a block of local values from a matrix.
1967 
1968    Not Collective; can only return values that are owned by the give process
1969 
1970    Input Parameters:
1971 +  mat - the matrix
1972 .  v - a logically two-dimensional array for storing the values
1973 .  m, idxm - the number of rows and their global indices
1974 -  n, idxn - the number of columns and their global indices
1975 
1976    Notes:
1977      The user must allocate space (m*n `PetscScalar`s) for the values, v.
1978      The values, v, are then returned in a row-oriented format,
1979      analogous to that used by default in `MatSetValues()`.
1980 
1981      `MatGetValues()` uses 0-based row and column numbers in
1982      Fortran as well as in C.
1983 
1984      `MatGetValues()` requires that the matrix has been assembled
1985      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
1986      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
1987      without intermediate matrix assembly.
1988 
1989      Negative row or column indices will be ignored and those locations in v[] will be
1990      left unchanged.
1991 
1992      For the standard row-based matrix formats, idxm[] can only contain rows owned by the requesting MPI rank.
1993      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
1994      from `MatGetOwnershipRange`(mat,&rstart,&rend).
1995 
1996    Level: advanced
1997 
1998 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
1999 @*/
2000 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[]) {
2001   PetscFunctionBegin;
2002   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2003   PetscValidType(mat, 1);
2004   if (!m || !n) PetscFunctionReturn(0);
2005   PetscValidIntPointer(idxm, 3);
2006   PetscValidIntPointer(idxn, 5);
2007   PetscValidScalarPointer(v, 6);
2008   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2009   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2010   MatCheckPreallocated(mat, 1);
2011 
2012   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2013   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2014   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2015   PetscFunctionReturn(0);
2016 }
2017 
2018 /*@C
2019    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2020      defined previously by `MatSetLocalToGlobalMapping()`
2021 
2022    Not Collective
2023 
2024    Input Parameters:
2025 +  mat - the matrix
2026 .  nrow, irow - number of rows and their local indices
2027 -  ncol, icol - number of columns and their local indices
2028 
2029    Output Parameter:
2030 .  y -  a logically two-dimensional array of values
2031 
2032    Notes:
2033      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2034 
2035      This routine can only return values that are owned by the requesting MPI rank. That is, for standard matrix formats, rows that, in the global numbering,
2036      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2037      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2038      with `MatSetLocalToGlobalMapping()`.
2039 
2040    Developer Note:
2041       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2042       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2043 
2044    Level: advanced
2045 
2046 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2047           `MatSetValuesLocal()`, `MatGetValues()`
2048 @*/
2049 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[]) {
2050   PetscFunctionBeginHot;
2051   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2052   PetscValidType(mat, 1);
2053   MatCheckPreallocated(mat, 1);
2054   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to retrieve */
2055   PetscValidIntPointer(irow, 3);
2056   PetscValidIntPointer(icol, 5);
2057   if (PetscDefined(USE_DEBUG)) {
2058     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2059     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2060   }
2061   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2062   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2063   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2064   else {
2065     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2066     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2067       irowm = buf;
2068       icolm = buf + nrow;
2069     } else {
2070       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2071       irowm = bufr;
2072       icolm = bufc;
2073     }
2074     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2075     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2076     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2077     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2078     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2079     PetscCall(PetscFree2(bufr, bufc));
2080   }
2081   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2082   PetscFunctionReturn(0);
2083 }
2084 
2085 /*@
2086   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2087   the same size. Currently, this can only be called once and creates the given matrix.
2088 
2089   Not Collective
2090 
2091   Input Parameters:
2092 + mat - the matrix
2093 . nb - the number of blocks
2094 . bs - the number of rows (and columns) in each block
2095 . rows - a concatenation of the rows for each block
2096 - v - a concatenation of logically two-dimensional arrays of values
2097 
2098   Note:
2099   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2100 
2101   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2102 
2103   Level: advanced
2104 
2105 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2106           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2107 @*/
2108 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[]) {
2109   PetscFunctionBegin;
2110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2111   PetscValidType(mat, 1);
2112   PetscValidIntPointer(rows, 4);
2113   PetscValidScalarPointer(v, 5);
2114   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2115 
2116   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2117   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2118   else {
2119     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2120   }
2121   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2122   PetscFunctionReturn(0);
2123 }
2124 
2125 /*@
2126    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2127    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2128    using a local (per-processor) numbering.
2129 
2130    Not Collective
2131 
2132    Input Parameters:
2133 +  x - the matrix
2134 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2135 -  cmapping - column mapping
2136 
2137    Level: intermediate
2138 
2139    Note:
2140    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2141 
2142 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2143 @*/
2144 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping) {
2145   PetscFunctionBegin;
2146   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2147   PetscValidType(x, 1);
2148   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2149   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2150   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2151   else {
2152     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2153     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2154   }
2155   PetscFunctionReturn(0);
2156 }
2157 
2158 /*@
2159    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2160 
2161    Not Collective
2162 
2163    Input Parameter:
2164 .  A - the matrix
2165 
2166    Output Parameters:
2167 + rmapping - row mapping
2168 - cmapping - column mapping
2169 
2170    Level: advanced
2171 
2172 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2173 @*/
2174 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping) {
2175   PetscFunctionBegin;
2176   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2177   PetscValidType(A, 1);
2178   if (rmapping) {
2179     PetscValidPointer(rmapping, 2);
2180     *rmapping = A->rmap->mapping;
2181   }
2182   if (cmapping) {
2183     PetscValidPointer(cmapping, 3);
2184     *cmapping = A->cmap->mapping;
2185   }
2186   PetscFunctionReturn(0);
2187 }
2188 
2189 /*@
2190    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2191 
2192    Logically Collective on A
2193 
2194    Input Parameters:
2195 +  A - the matrix
2196 . rmap - row layout
2197 - cmap - column layout
2198 
2199    Level: advanced
2200 
2201    Note:
2202    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2203 
2204 .seealso: `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2205 @*/
2206 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap) {
2207   PetscFunctionBegin;
2208   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2209   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2210   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2211   PetscFunctionReturn(0);
2212 }
2213 
2214 /*@
2215    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2216 
2217    Not Collective
2218 
2219    Input Parameter:
2220 .  A - the matrix
2221 
2222    Output Parameters:
2223 + rmap - row layout
2224 - cmap - column layout
2225 
2226    Level: advanced
2227 
2228 .seealso: [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2229 @*/
2230 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap) {
2231   PetscFunctionBegin;
2232   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2233   PetscValidType(A, 1);
2234   if (rmap) {
2235     PetscValidPointer(rmap, 2);
2236     *rmap = A->rmap;
2237   }
2238   if (cmap) {
2239     PetscValidPointer(cmap, 3);
2240     *cmap = A->cmap;
2241   }
2242   PetscFunctionReturn(0);
2243 }
2244 
2245 /*@C
2246    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2247    using a local numbering of the nodes.
2248 
2249    Not Collective
2250 
2251    Input Parameters:
2252 +  mat - the matrix
2253 .  nrow, irow - number of rows and their local indices
2254 .  ncol, icol - number of columns and their local indices
2255 .  y -  a logically two-dimensional array of values
2256 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2257 
2258    Notes:
2259    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2260       `MatSetUp()` before using this routine
2261 
2262    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2263 
2264    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2265    options cannot be mixed without intervening calls to the assembly
2266    routines.
2267 
2268    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2269    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2270 
2271    Level: intermediate
2272 
2273    Developer Note:
2274     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2275                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2276 
2277 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2278           `MatGetValuesLocal()`
2279 @*/
2280 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) {
2281   PetscFunctionBeginHot;
2282   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2283   PetscValidType(mat, 1);
2284   MatCheckPreallocated(mat, 1);
2285   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2286   PetscValidIntPointer(irow, 3);
2287   PetscValidIntPointer(icol, 5);
2288   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2289   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2290   if (PetscDefined(USE_DEBUG)) {
2291     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2292     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2293   }
2294 
2295   if (mat->assembled) {
2296     mat->was_assembled = PETSC_TRUE;
2297     mat->assembled     = PETSC_FALSE;
2298   }
2299   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2300   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2301   else {
2302     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2303     const PetscInt *irowm, *icolm;
2304 
2305     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2306       bufr  = buf;
2307       bufc  = buf + nrow;
2308       irowm = bufr;
2309       icolm = bufc;
2310     } else {
2311       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2312       irowm = bufr;
2313       icolm = bufc;
2314     }
2315     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2316     else irowm = irow;
2317     if (mat->cmap->mapping) {
2318       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2319         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2320       } else icolm = irowm;
2321     } else icolm = icol;
2322     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2323     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2324   }
2325   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2326   PetscFunctionReturn(0);
2327 }
2328 
2329 /*@C
2330    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2331    using a local ordering of the nodes a block at a time.
2332 
2333    Not Collective
2334 
2335    Input Parameters:
2336 +  x - the matrix
2337 .  nrow, irow - number of rows and their local indices
2338 .  ncol, icol - number of columns and their local indices
2339 .  y -  a logically two-dimensional array of values
2340 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2341 
2342    Notes:
2343    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2344       `MatSetUp()` before using this routine
2345 
2346    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2347       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2348 
2349    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2350    options cannot be mixed without intervening calls to the assembly
2351    routines.
2352 
2353    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2354    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2355 
2356    Level: intermediate
2357 
2358    Developer Note:
2359     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2360                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2361 
2362 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2363           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2364 @*/
2365 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv) {
2366   PetscFunctionBeginHot;
2367   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2368   PetscValidType(mat, 1);
2369   MatCheckPreallocated(mat, 1);
2370   if (!nrow || !ncol) PetscFunctionReturn(0); /* no values to insert */
2371   PetscValidIntPointer(irow, 3);
2372   PetscValidIntPointer(icol, 5);
2373   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2374   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2375   if (PetscDefined(USE_DEBUG)) {
2376     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2377     PetscCheck(mat->ops->setvaluesblockedlocal || mat->ops->setvaluesblocked || mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2378   }
2379 
2380   if (mat->assembled) {
2381     mat->was_assembled = PETSC_TRUE;
2382     mat->assembled     = PETSC_FALSE;
2383   }
2384   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2385     PetscInt irbs, rbs;
2386     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2387     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2388     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2389   }
2390   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2391     PetscInt icbs, cbs;
2392     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2393     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2394     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2395   }
2396   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2397   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2398   else {
2399     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2400     const PetscInt *irowm, *icolm;
2401 
2402     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2403       bufr  = buf;
2404       bufc  = buf + nrow;
2405       irowm = bufr;
2406       icolm = bufc;
2407     } else {
2408       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2409       irowm = bufr;
2410       icolm = bufc;
2411     }
2412     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2413     else irowm = irow;
2414     if (mat->cmap->mapping) {
2415       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2416         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2417       } else icolm = irowm;
2418     } else icolm = icol;
2419     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2420     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2421   }
2422   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2423   PetscFunctionReturn(0);
2424 }
2425 
2426 /*@
2427    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2428 
2429    Collective on mat
2430 
2431    Input Parameters:
2432 +  mat - the matrix
2433 -  x   - the vector to be multiplied
2434 
2435    Output Parameters:
2436 .  y - the result
2437 
2438    Note:
2439    The vectors x and y cannot be the same.  I.e., one cannot
2440    call `MatMultDiagonalBlock`(A,y,y).
2441 
2442    Level: developer
2443 
2444 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2445 @*/
2446 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y) {
2447   PetscFunctionBegin;
2448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2449   PetscValidType(mat, 1);
2450   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2451   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2452 
2453   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2454   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2455   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2456   MatCheckPreallocated(mat, 1);
2457 
2458   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2459   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2460   PetscFunctionReturn(0);
2461 }
2462 
2463 /* --------------------------------------------------------*/
2464 /*@
2465    MatMult - Computes the matrix-vector product, y = Ax.
2466 
2467    Neighbor-wise Collective on mat
2468 
2469    Input Parameters:
2470 +  mat - the matrix
2471 -  x   - the vector to be multiplied
2472 
2473    Output Parameters:
2474 .  y - the result
2475 
2476    Note:
2477    The vectors x and y cannot be the same.  I.e., one cannot
2478    call `MatMult`(A,y,y).
2479 
2480    Level: beginner
2481 
2482 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2483 @*/
2484 PetscErrorCode MatMult(Mat mat, Vec x, Vec y) {
2485   PetscFunctionBegin;
2486   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2487   PetscValidType(mat, 1);
2488   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2489   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2492   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2493   PetscCheck(mat->cmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, x->map->N);
2494   PetscCheck(mat->rmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, y->map->N);
2495   PetscCheck(mat->cmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, x->map->n);
2496   PetscCheck(mat->rmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, y->map->n);
2497   PetscCall(VecSetErrorIfLocked(y, 3));
2498   if (mat->erroriffailure) PetscCall(VecValidValues(x, 2, PETSC_TRUE));
2499   MatCheckPreallocated(mat, 1);
2500 
2501   PetscCall(VecLockReadPush(x));
2502   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2503   PetscUseTypeMethod(mat, mult, x, y);
2504   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2505   if (mat->erroriffailure) PetscCall(VecValidValues(y, 3, PETSC_FALSE));
2506   PetscCall(VecLockReadPop(x));
2507   PetscFunctionReturn(0);
2508 }
2509 
2510 /*@
2511    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2512 
2513    Neighbor-wise Collective on mat
2514 
2515    Input Parameters:
2516 +  mat - the matrix
2517 -  x   - the vector to be multiplied
2518 
2519    Output Parameters:
2520 .  y - the result
2521 
2522    Notes:
2523    The vectors x and y cannot be the same.  I.e., one cannot
2524    call `MatMultTranspose`(A,y,y).
2525 
2526    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2527    use `MatMultHermitianTranspose()`
2528 
2529    Level: beginner
2530 
2531 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2532 @*/
2533 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y) {
2534   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2535 
2536   PetscFunctionBegin;
2537   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2538   PetscValidType(mat, 1);
2539   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2540   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2541 
2542   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2543   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2544   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2545   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2546   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2547   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2548   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2549   if (mat->erroriffailure) PetscCall(VecValidValues(x, 2, PETSC_TRUE));
2550   MatCheckPreallocated(mat, 1);
2551 
2552   if (!mat->ops->multtranspose) {
2553     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2554     PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s does not have a multiply transpose defined or is symmetric and does not have a multiply defined", ((PetscObject)mat)->type_name);
2555   } else op = mat->ops->multtranspose;
2556   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2557   PetscCall(VecLockReadPush(x));
2558   PetscCall((*op)(mat, x, y));
2559   PetscCall(VecLockReadPop(x));
2560   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2561   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2562   if (mat->erroriffailure) PetscCall(VecValidValues(y, 3, PETSC_FALSE));
2563   PetscFunctionReturn(0);
2564 }
2565 
2566 /*@
2567    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2568 
2569    Neighbor-wise Collective on mat
2570 
2571    Input Parameters:
2572 +  mat - the matrix
2573 -  x   - the vector to be multilplied
2574 
2575    Output Parameters:
2576 .  y - the result
2577 
2578    Notes:
2579    The vectors x and y cannot be the same.  I.e., one cannot
2580    call `MatMultHermitianTranspose`(A,y,y).
2581 
2582    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2583 
2584    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2585 
2586    Level: beginner
2587 
2588 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2589 @*/
2590 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y) {
2591   PetscFunctionBegin;
2592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2593   PetscValidType(mat, 1);
2594   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2595   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2596 
2597   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2598   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2599   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2600   PetscCheck(mat->cmap->N == y->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, y->map->N);
2601   PetscCheck(mat->rmap->N == x->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, x->map->N);
2602   PetscCheck(mat->cmap->n == y->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec y: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->n, y->map->n);
2603   PetscCheck(mat->rmap->n == x->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec x: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, x->map->n);
2604   MatCheckPreallocated(mat, 1);
2605 
2606   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2607 #if defined(PETSC_USE_COMPLEX)
2608   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2609     PetscCall(VecLockReadPush(x));
2610     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2611     else PetscUseTypeMethod(mat, mult, x, y);
2612     PetscCall(VecLockReadPop(x));
2613   } else {
2614     Vec w;
2615     PetscCall(VecDuplicate(x, &w));
2616     PetscCall(VecCopy(x, w));
2617     PetscCall(VecConjugate(w));
2618     PetscCall(MatMultTranspose(mat, w, y));
2619     PetscCall(VecDestroy(&w));
2620     PetscCall(VecConjugate(y));
2621   }
2622   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2623 #else
2624   PetscCall(MatMultTranspose(mat, x, y));
2625 #endif
2626   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2627   PetscFunctionReturn(0);
2628 }
2629 
2630 /*@
2631     MatMultAdd -  Computes v3 = v2 + A * v1.
2632 
2633     Neighbor-wise Collective on mat
2634 
2635     Input Parameters:
2636 +   mat - the matrix
2637 -   v1, v2 - the vectors
2638 
2639     Output Parameters:
2640 .   v3 - the result
2641 
2642     Note:
2643     The vectors v1 and v3 cannot be the same.  I.e., one cannot
2644     call `MatMultAdd`(A,v1,v2,v1).
2645 
2646     Level: beginner
2647 
2648 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2649 @*/
2650 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3) {
2651   PetscFunctionBegin;
2652   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2653   PetscValidType(mat, 1);
2654   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2655   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2656   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2657 
2658   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2659   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2660   PetscCheck(mat->cmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v1->map->N);
2661   /* PetscCheck(mat->rmap->N == v2->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v2->map->N);
2662      PetscCheck(mat->rmap->N == v3->map->N,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT,mat->rmap->N,v3->map->N); */
2663   PetscCheck(mat->rmap->n == v3->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v3->map->n);
2664   PetscCheck(mat->rmap->n == v2->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, v2->map->n);
2665   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2666   MatCheckPreallocated(mat, 1);
2667 
2668   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2669   PetscCall(VecLockReadPush(v1));
2670   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2671   PetscCall(VecLockReadPop(v1));
2672   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2673   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2674   PetscFunctionReturn(0);
2675 }
2676 
2677 /*@
2678    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2679 
2680    Neighbor-wise Collective on mat
2681 
2682    Input Parameters:
2683 +  mat - the matrix
2684 -  v1, v2 - the vectors
2685 
2686    Output Parameters:
2687 .  v3 - the result
2688 
2689    Note:
2690    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2691    call `MatMultTransposeAdd`(A,v1,v2,v1).
2692 
2693    Level: beginner
2694 
2695 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2696 @*/
2697 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) {
2698   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2699 
2700   PetscFunctionBegin;
2701   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2702   PetscValidType(mat, 1);
2703   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2704   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2705   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2706 
2707   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2708   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2709   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2710   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2711   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2712   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2713   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2714   MatCheckPreallocated(mat, 1);
2715 
2716   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2717   PetscCall(VecLockReadPush(v1));
2718   PetscCall((*op)(mat, v1, v2, v3));
2719   PetscCall(VecLockReadPop(v1));
2720   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2721   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2722   PetscFunctionReturn(0);
2723 }
2724 
2725 /*@
2726    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2727 
2728    Neighbor-wise Collective on mat
2729 
2730    Input Parameters:
2731 +  mat - the matrix
2732 -  v1, v2 - the vectors
2733 
2734    Output Parameters:
2735 .  v3 - the result
2736 
2737    Note:
2738    The vectors v1 and v3 cannot be the same.  I.e., one cannot
2739    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2740 
2741    Level: beginner
2742 
2743 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2744 @*/
2745 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3) {
2746   PetscFunctionBegin;
2747   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2748   PetscValidType(mat, 1);
2749   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2750   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2751   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2752 
2753   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2754   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2755   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2756   PetscCheck(mat->rmap->N == v1->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v1: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->N, v1->map->N);
2757   PetscCheck(mat->cmap->N == v2->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v2: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v2->map->N);
2758   PetscCheck(mat->cmap->N == v3->map->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_SIZ, "Mat mat,Vec v3: global dim %" PetscInt_FMT " %" PetscInt_FMT, mat->cmap->N, v3->map->N);
2759   MatCheckPreallocated(mat, 1);
2760 
2761   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2762   PetscCall(VecLockReadPush(v1));
2763   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2764   else {
2765     Vec w, z;
2766     PetscCall(VecDuplicate(v1, &w));
2767     PetscCall(VecCopy(v1, w));
2768     PetscCall(VecConjugate(w));
2769     PetscCall(VecDuplicate(v3, &z));
2770     PetscCall(MatMultTranspose(mat, w, z));
2771     PetscCall(VecDestroy(&w));
2772     PetscCall(VecConjugate(z));
2773     if (v2 != v3) {
2774       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2775     } else {
2776       PetscCall(VecAXPY(v3, 1.0, z));
2777     }
2778     PetscCall(VecDestroy(&z));
2779   }
2780   PetscCall(VecLockReadPop(v1));
2781   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2782   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2783   PetscFunctionReturn(0);
2784 }
2785 
2786 /*@C
2787    MatGetFactorType - gets the type of factorization it is
2788 
2789    Not Collective
2790 
2791    Input Parameters:
2792 .  mat - the matrix
2793 
2794    Output Parameters:
2795 .  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2796 
2797    Level: intermediate
2798 
2799 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2800           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2801 @*/
2802 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t) {
2803   PetscFunctionBegin;
2804   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2805   PetscValidType(mat, 1);
2806   PetscValidPointer(t, 2);
2807   *t = mat->factortype;
2808   PetscFunctionReturn(0);
2809 }
2810 
2811 /*@C
2812    MatSetFactorType - sets the type of factorization it is
2813 
2814    Logically Collective on mat
2815 
2816    Input Parameters:
2817 +  mat - the matrix
2818 -  t - the type, one of `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`, `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2819 
2820    Level: intermediate
2821 
2822 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2823           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2824 @*/
2825 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t) {
2826   PetscFunctionBegin;
2827   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2828   PetscValidType(mat, 1);
2829   mat->factortype = t;
2830   PetscFunctionReturn(0);
2831 }
2832 
2833 /* ------------------------------------------------------------*/
2834 /*@C
2835    MatGetInfo - Returns information about matrix storage (number of
2836    nonzeros, memory, etc.).
2837 
2838    Collective on mat if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2839 
2840    Input Parameter:
2841 .  mat - the matrix
2842 
2843    Output Parameters:
2844 +  flag - flag indicating the type of parameters to be returned
2845    (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors,
2846    MAT_GLOBAL_SUM - sum over all processors)
2847 -  info - matrix information context
2848 
2849    Notes:
2850    The `MatInfo` context contains a variety of matrix data, including
2851    number of nonzeros allocated and used, number of mallocs during
2852    matrix assembly, etc.  Additional information for factored matrices
2853    is provided (such as the fill ratio, number of mallocs during
2854    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2855    when using the runtime options
2856 $       -info -mat_view ::ascii_info
2857 
2858    Example for C/C++ Users:
2859    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2860    data within the MatInfo context.  For example,
2861 .vb
2862       MatInfo info;
2863       Mat     A;
2864       double  mal, nz_a, nz_u;
2865 
2866       MatGetInfo(A,MAT_LOCAL,&info);
2867       mal  = info.mallocs;
2868       nz_a = info.nz_allocated;
2869 .ve
2870 
2871    Example for Fortran Users:
2872    Fortran users should declare info as a double precision
2873    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2874    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2875    a complete list of parameter names.
2876 .vb
2877       double  precision info(MAT_INFO_SIZE)
2878       double  precision mal, nz_a
2879       Mat     A
2880       integer ierr
2881 
2882       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2883       mal = info(MAT_INFO_MALLOCS)
2884       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2885 .ve
2886 
2887     Level: intermediate
2888 
2889     Developer Note: fortran interface is not autogenerated as the f90
2890     interface definition cannot be generated correctly [due to MatInfo]
2891 
2892 .seealso: `MatInfo`, `MatStashGetInfo()`
2893 @*/
2894 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info) {
2895   PetscFunctionBegin;
2896   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2897   PetscValidType(mat, 1);
2898   PetscValidPointer(info, 3);
2899   MatCheckPreallocated(mat, 1);
2900   PetscUseTypeMethod(mat, getinfo, flag, info);
2901   PetscFunctionReturn(0);
2902 }
2903 
2904 /*
2905    This is used by external packages where it is not easy to get the info from the actual
2906    matrix factorization.
2907 */
2908 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info) {
2909   PetscFunctionBegin;
2910   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2911   PetscFunctionReturn(0);
2912 }
2913 
2914 /* ----------------------------------------------------------*/
2915 
2916 /*@C
2917    MatLUFactor - Performs in-place LU factorization of matrix.
2918 
2919    Collective on mat
2920 
2921    Input Parameters:
2922 +  mat - the matrix
2923 .  row - row permutation
2924 .  col - column permutation
2925 -  info - options for factorization, includes
2926 $          fill - expected fill as ratio of original fill.
2927 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
2928 $                   Run with the option -info to determine an optimal value to use
2929 
2930    Notes:
2931    Most users should employ the `KSP` interface for linear solvers
2932    instead of working directly with matrix algebra routines such as this.
2933    See, e.g., `KSPCreate()`.
2934 
2935    This changes the state of the matrix to a factored matrix; it cannot be used
2936    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
2937 
2938    This is really in-place only for dense matrices, the prefered approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
2939    when not using `KSP`.
2940 
2941    Level: developer
2942 
2943    Developer Note:
2944    The Fortran interface is not autogenerated as the f90
2945    interface definition cannot be generated correctly [due to `MatFactorInfo`]
2946 
2947 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
2948           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
2949 @*/
2950 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) {
2951   MatFactorInfo tinfo;
2952 
2953   PetscFunctionBegin;
2954   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2955   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
2956   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
2957   if (info) PetscValidPointer(info, 4);
2958   PetscValidType(mat, 1);
2959   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2960   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2961   MatCheckPreallocated(mat, 1);
2962   if (!info) {
2963     PetscCall(MatFactorInfoInitialize(&tinfo));
2964     info = &tinfo;
2965   }
2966 
2967   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
2968   PetscUseTypeMethod(mat, lufactor, row, col, info);
2969   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
2970   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
2971   PetscFunctionReturn(0);
2972 }
2973 
2974 /*@C
2975    MatILUFactor - Performs in-place ILU factorization of matrix.
2976 
2977    Collective on mat
2978 
2979    Input Parameters:
2980 +  mat - the matrix
2981 .  row - row permutation
2982 .  col - column permutation
2983 -  info - structure containing
2984 $      levels - number of levels of fill.
2985 $      expected fill - as ratio of original fill.
2986 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
2987                 missing diagonal entries)
2988 
2989    Notes:
2990    Most users should employ the `KSP` interface for linear solvers
2991    instead of working directly with matrix algebra routines such as this.
2992    See, e.g., `KSPCreate()`.
2993 
2994    Probably really in-place only when level of fill is zero, otherwise allocates
2995    new space to store factored matrix and deletes previous memory. The prefered approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
2996    when not using `KSP`.
2997 
2998    Level: developer
2999 
3000    Developer Note:
3001    The Fortran interface is not autogenerated as the f90
3002    interface definition cannot be generated correctly [due to MatFactorInfo]
3003 
3004 .seealso: [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3005 @*/
3006 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info) {
3007   PetscFunctionBegin;
3008   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3009   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3010   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3011   PetscValidPointer(info, 4);
3012   PetscValidType(mat, 1);
3013   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3014   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3015   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3016   MatCheckPreallocated(mat, 1);
3017 
3018   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3019   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3020   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3021   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3022   PetscFunctionReturn(0);
3023 }
3024 
3025 /*@C
3026    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3027    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3028 
3029    Collective on fact
3030 
3031    Input Parameters:
3032 +  fact - the factor matrix obtained with `MatGetFactor()`
3033 .  mat - the matrix
3034 .  row, col - row and column permutations
3035 -  info - options for factorization, includes
3036 .vb
3037           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3038           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3039 .ve
3040 
3041    Notes:
3042     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3043 
3044    Most users should employ the simplified `KSP` interface for linear solvers
3045    instead of working directly with matrix algebra routines such as this.
3046    See, e.g., `KSPCreate()`.
3047 
3048    Level: developer
3049 
3050    Developer Note:
3051    The Fortran interface is not autogenerated as the f90
3052    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3053 
3054 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3055 @*/
3056 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) {
3057   MatFactorInfo tinfo;
3058 
3059   PetscFunctionBegin;
3060   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3061   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3062   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3063   if (info) PetscValidPointer(info, 5);
3064   PetscValidType(mat, 2);
3065   PetscValidPointer(fact, 1);
3066   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3067   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3068   if (!(fact)->ops->lufactorsymbolic) {
3069     MatSolverType stype;
3070     PetscCall(MatFactorGetSolverType(fact, &stype));
3071     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3072   }
3073   MatCheckPreallocated(mat, 2);
3074   if (!info) {
3075     PetscCall(MatFactorInfoInitialize(&tinfo));
3076     info = &tinfo;
3077   }
3078 
3079   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3080   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3081   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3082   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3083   PetscFunctionReturn(0);
3084 }
3085 
3086 /*@C
3087    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3088    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3089 
3090    Collective on fact
3091 
3092    Input Parameters:
3093 +  fact - the factor matrix obtained with `MatGetFactor()`
3094 .  mat - the matrix
3095 -  info - options for factorization
3096 
3097    Notes:
3098    See `MatLUFactor()` for in-place factorization.  See
3099    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3100 
3101    Most users should employ the `KSP` interface for linear solvers
3102    instead of working directly with matrix algebra routines such as this.
3103    See, e.g., `KSPCreate()`.
3104 
3105    Level: developer
3106 
3107     Developer Note:
3108     The Fortran interface is not autogenerated as the f90
3109     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3110 
3111 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3112 @*/
3113 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) {
3114   MatFactorInfo tinfo;
3115 
3116   PetscFunctionBegin;
3117   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3118   PetscValidType(mat, 2);
3119   PetscValidPointer(fact, 1);
3120   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3121   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3122   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,
3123              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3124 
3125   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3126   MatCheckPreallocated(mat, 2);
3127   if (!info) {
3128     PetscCall(MatFactorInfoInitialize(&tinfo));
3129     info = &tinfo;
3130   }
3131 
3132   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3133   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3134   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3135   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3136   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3137   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3138   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3139   PetscFunctionReturn(0);
3140 }
3141 
3142 /*@C
3143    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3144    symmetric matrix.
3145 
3146    Collective on mat
3147 
3148    Input Parameters:
3149 +  mat - the matrix
3150 .  perm - row and column permutations
3151 -  f - expected fill as ratio of original fill
3152 
3153    Notes:
3154    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3155    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3156 
3157    Most users should employ the `KSP` interface for linear solvers
3158    instead of working directly with matrix algebra routines such as this.
3159    See, e.g., `KSPCreate()`.
3160 
3161    Level: developer
3162 
3163    Developer Note:
3164    The Fortran interface is not autogenerated as the f90
3165    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3166 
3167 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3168           `MatGetOrdering()`
3169 @*/
3170 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info) {
3171   MatFactorInfo tinfo;
3172 
3173   PetscFunctionBegin;
3174   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3175   PetscValidType(mat, 1);
3176   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3177   if (info) PetscValidPointer(info, 3);
3178   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3179   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3180   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3181   MatCheckPreallocated(mat, 1);
3182   if (!info) {
3183     PetscCall(MatFactorInfoInitialize(&tinfo));
3184     info = &tinfo;
3185   }
3186 
3187   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3188   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3189   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3190   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3191   PetscFunctionReturn(0);
3192 }
3193 
3194 /*@C
3195    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3196    of a symmetric matrix.
3197 
3198    Collective on fact
3199 
3200    Input Parameters:
3201 +  fact - the factor matrix obtained with `MatGetFactor()`
3202 .  mat - the matrix
3203 .  perm - row and column permutations
3204 -  info - options for factorization, includes
3205 $          fill - expected fill as ratio of original fill.
3206 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3207 $                   Run with the option -info to determine an optimal value to use
3208 
3209    Notes:
3210    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3211    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3212 
3213    Most users should employ the `KSP` interface for linear solvers
3214    instead of working directly with matrix algebra routines such as this.
3215    See, e.g., `KSPCreate()`.
3216 
3217    Level: developer
3218 
3219    Developer Note:
3220    The Fortran interface is not autogenerated as the f90
3221    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3222 
3223 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3224           `MatGetOrdering()`
3225 @*/
3226 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) {
3227   MatFactorInfo tinfo;
3228 
3229   PetscFunctionBegin;
3230   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3231   PetscValidType(mat, 2);
3232   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3233   if (info) PetscValidPointer(info, 4);
3234   PetscValidPointer(fact, 1);
3235   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3236   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3237   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3238   if (!(fact)->ops->choleskyfactorsymbolic) {
3239     MatSolverType stype;
3240     PetscCall(MatFactorGetSolverType(fact, &stype));
3241     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3242   }
3243   MatCheckPreallocated(mat, 2);
3244   if (!info) {
3245     PetscCall(MatFactorInfoInitialize(&tinfo));
3246     info = &tinfo;
3247   }
3248 
3249   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3250   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3251   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3252   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3253   PetscFunctionReturn(0);
3254 }
3255 
3256 /*@C
3257    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3258    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3259    `MatCholeskyFactorSymbolic()`.
3260 
3261    Collective on fact
3262 
3263    Input Parameters:
3264 +  fact - the factor matrix obtained with `MatGetFactor()`
3265 .  mat - the initial matrix
3266 .  info - options for factorization
3267 -  fact - the symbolic factor of mat
3268 
3269    Note:
3270    Most users should employ the `KSP` interface for linear solvers
3271    instead of working directly with matrix algebra routines such as this.
3272    See, e.g., `KSPCreate()`.
3273 
3274    Level: developer
3275 
3276    Developer Note:
3277    The Fortran interface is not autogenerated as the f90
3278    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3279 
3280 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3281 @*/
3282 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) {
3283   MatFactorInfo tinfo;
3284 
3285   PetscFunctionBegin;
3286   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3287   PetscValidType(mat, 2);
3288   PetscValidPointer(fact, 1);
3289   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3290   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3291   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3292   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,
3293              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3294   MatCheckPreallocated(mat, 2);
3295   if (!info) {
3296     PetscCall(MatFactorInfoInitialize(&tinfo));
3297     info = &tinfo;
3298   }
3299 
3300   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3301   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3302   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3303   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3304   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3305   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3306   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3307   PetscFunctionReturn(0);
3308 }
3309 
3310 /*@
3311    MatQRFactor - Performs in-place QR factorization of matrix.
3312 
3313    Collective on mat
3314 
3315    Input Parameters:
3316 +  mat - the matrix
3317 .  col - column permutation
3318 -  info - options for factorization, includes
3319 $          fill - expected fill as ratio of original fill.
3320 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3321 $                   Run with the option -info to determine an optimal value to use
3322 
3323    Notes:
3324    Most users should employ the `KSP` interface for linear solvers
3325    instead of working directly with matrix algebra routines such as this.
3326    See, e.g., `KSPCreate()`.
3327 
3328    This changes the state of the matrix to a factored matrix; it cannot be used
3329    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3330 
3331    Level: developer
3332 
3333    Developer Note:
3334    The Fortran interface is not autogenerated as the f90
3335    interface definition cannot be generated correctly [due to MatFactorInfo]
3336 
3337 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3338           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3339 @*/
3340 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info) {
3341   PetscFunctionBegin;
3342   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3343   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3344   if (info) PetscValidPointer(info, 3);
3345   PetscValidType(mat, 1);
3346   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3347   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3348   MatCheckPreallocated(mat, 1);
3349   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3350   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3351   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3352   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3353   PetscFunctionReturn(0);
3354 }
3355 
3356 /*@
3357    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3358    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3359 
3360    Collective on fact
3361 
3362    Input Parameters:
3363 +  fact - the factor matrix obtained with `MatGetFactor()`
3364 .  mat - the matrix
3365 .  col - column permutation
3366 -  info - options for factorization, includes
3367 $          fill - expected fill as ratio of original fill.
3368 $          dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3369 $                   Run with the option -info to determine an optimal value to use
3370 
3371    Most users should employ the `KSP` interface for linear solvers
3372    instead of working directly with matrix algebra routines such as this.
3373    See, e.g., `KSPCreate()`.
3374 
3375    Level: developer
3376 
3377    Developer Note:
3378    The Fortran interface is not autogenerated as the f90
3379    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3380 
3381 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3382 @*/
3383 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info) {
3384   MatFactorInfo tinfo;
3385 
3386   PetscFunctionBegin;
3387   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3388   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3389   if (info) PetscValidPointer(info, 4);
3390   PetscValidType(mat, 2);
3391   PetscValidPointer(fact, 1);
3392   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3393   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3394   MatCheckPreallocated(mat, 2);
3395   if (!info) {
3396     PetscCall(MatFactorInfoInitialize(&tinfo));
3397     info = &tinfo;
3398   }
3399 
3400   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3401   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3402   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3403   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3404   PetscFunctionReturn(0);
3405 }
3406 
3407 /*@
3408    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3409    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3410 
3411    Collective on fact
3412 
3413    Input Parameters:
3414 +  fact - the factor matrix obtained with `MatGetFactor()`
3415 .  mat - the matrix
3416 -  info - options for factorization
3417 
3418    Notes:
3419    See `MatQRFactor()` for in-place factorization.
3420 
3421    Most users should employ the `KSP` interface for linear solvers
3422    instead of working directly with matrix algebra routines such as this.
3423    See, e.g., `KSPCreate()`.
3424 
3425    Level: developer
3426 
3427    Developer Note:
3428    The Fortran interface is not autogenerated as the f90
3429    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3430 
3431 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3432 @*/
3433 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info) {
3434   MatFactorInfo tinfo;
3435 
3436   PetscFunctionBegin;
3437   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3438   PetscValidType(mat, 2);
3439   PetscValidPointer(fact, 1);
3440   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3441   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3442   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,
3443              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3444 
3445   MatCheckPreallocated(mat, 2);
3446   if (!info) {
3447     PetscCall(MatFactorInfoInitialize(&tinfo));
3448     info = &tinfo;
3449   }
3450 
3451   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3452   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3453   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3454   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3455   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3456   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3457   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3458   PetscFunctionReturn(0);
3459 }
3460 
3461 /* ----------------------------------------------------------------*/
3462 /*@
3463    MatSolve - Solves A x = b, given a factored matrix.
3464 
3465    Neighbor-wise Collective on mat
3466 
3467    Input Parameters:
3468 +  mat - the factored matrix
3469 -  b - the right-hand-side vector
3470 
3471    Output Parameter:
3472 .  x - the result vector
3473 
3474    Notes:
3475    The vectors b and x cannot be the same.  I.e., one cannot
3476    call `MatSolve`(A,x,x).
3477 
3478    Most users should employ the `KSP` interface for linear solvers
3479    instead of working directly with matrix algebra routines such as this.
3480    See, e.g., `KSPCreate()`.
3481 
3482    Level: developer
3483 
3484 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3485 @*/
3486 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x) {
3487   PetscFunctionBegin;
3488   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3489   PetscValidType(mat, 1);
3490   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3491   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3492   PetscCheckSameComm(mat, 1, b, 2);
3493   PetscCheckSameComm(mat, 1, x, 3);
3494   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3495   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);
3496   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);
3497   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);
3498   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3499   MatCheckPreallocated(mat, 1);
3500 
3501   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3502   if (mat->factorerrortype) {
3503     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3504     PetscCall(VecSetInf(x));
3505   } else PetscUseTypeMethod(mat, solve, b, x);
3506   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3507   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3508   PetscFunctionReturn(0);
3509 }
3510 
3511 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans) {
3512   Vec      b, x;
3513   PetscInt N, i;
3514   PetscErrorCode (*f)(Mat, Vec, Vec);
3515   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3516 
3517   PetscFunctionBegin;
3518   if (A->factorerrortype) {
3519     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3520     PetscCall(MatSetInf(X));
3521     PetscFunctionReturn(0);
3522   }
3523   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3524   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3525   PetscCall(MatBoundToCPU(A, &Abound));
3526   if (!Abound) {
3527     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3528     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3529   }
3530   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3531   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3532   PetscCall(MatGetSize(B, NULL, &N));
3533   for (i = 0; i < N; i++) {
3534     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3535     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3536     PetscCall((*f)(A, b, x));
3537     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3538     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3539   }
3540   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3541   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3542   PetscFunctionReturn(0);
3543 }
3544 
3545 /*@
3546    MatMatSolve - Solves A X = B, given a factored matrix.
3547 
3548    Neighbor-wise Collective on A
3549 
3550    Input Parameters:
3551 +  A - the factored matrix
3552 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3553 
3554    Output Parameter:
3555 .  X - the result matrix (dense matrix)
3556 
3557    Note:
3558    If B is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with MKL_CPARDISO;
3559    otherwise, B and X cannot be the same.
3560 
3561    Level: developer
3562 
3563 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3564 @*/
3565 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X) {
3566   PetscFunctionBegin;
3567   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3568   PetscValidType(A, 1);
3569   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3570   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3571   PetscCheckSameComm(A, 1, B, 2);
3572   PetscCheckSameComm(A, 1, X, 3);
3573   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);
3574   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);
3575   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");
3576   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3577   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3578   MatCheckPreallocated(A, 1);
3579 
3580   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3581   if (!A->ops->matsolve) {
3582     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3583     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3584   } else PetscUseTypeMethod(A, matsolve, B, X);
3585   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3586   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3587   PetscFunctionReturn(0);
3588 }
3589 
3590 /*@
3591    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3592 
3593    Neighbor-wise Collective on A
3594 
3595    Input Parameters:
3596 +  A - the factored matrix
3597 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3598 
3599    Output Parameter:
3600 .  X - the result matrix (dense matrix)
3601 
3602    Note:
3603    The matrices B and X cannot be the same.  I.e., one cannot
3604    call `MatMatSolveTranspose`(A,X,X).
3605 
3606    Level: developer
3607 
3608 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3609 @*/
3610 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X) {
3611   PetscFunctionBegin;
3612   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3613   PetscValidType(A, 1);
3614   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3615   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3616   PetscCheckSameComm(A, 1, B, 2);
3617   PetscCheckSameComm(A, 1, X, 3);
3618   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3619   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);
3620   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);
3621   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);
3622   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");
3623   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3624   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3625   MatCheckPreallocated(A, 1);
3626 
3627   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3628   if (!A->ops->matsolvetranspose) {
3629     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3630     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3631   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3632   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3633   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3634   PetscFunctionReturn(0);
3635 }
3636 
3637 /*@
3638    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3639 
3640    Neighbor-wise Collective on A
3641 
3642    Input Parameters:
3643 +  A - the factored matrix
3644 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3645 
3646    Output Parameter:
3647 .  X - the result matrix (dense matrix)
3648 
3649    Note:
3650    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
3651    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3652 
3653    Level: developer
3654 
3655 .seealso: [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3656 @*/
3657 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X) {
3658   PetscFunctionBegin;
3659   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3660   PetscValidType(A, 1);
3661   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3662   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3663   PetscCheckSameComm(A, 1, Bt, 2);
3664   PetscCheckSameComm(A, 1, X, 3);
3665 
3666   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3667   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);
3668   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);
3669   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");
3670   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(0);
3671   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3672   MatCheckPreallocated(A, 1);
3673 
3674   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3675   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3676   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3677   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3678   PetscFunctionReturn(0);
3679 }
3680 
3681 /*@
3682    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3683                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3684 
3685    Neighbor-wise Collective on mat
3686 
3687    Input Parameters:
3688 +  mat - the factored matrix
3689 -  b - the right-hand-side vector
3690 
3691    Output Parameter:
3692 .  x - the result vector
3693 
3694    Notes:
3695    `MatSolve()` should be used for most applications, as it performs
3696    a forward solve followed by a backward solve.
3697 
3698    The vectors b and x cannot be the same,  i.e., one cannot
3699    call `MatForwardSolve`(A,x,x).
3700 
3701    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3702    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3703    `MatForwardSolve()` solves U^T*D y = b, and
3704    `MatBackwardSolve()` solves U x = y.
3705    Thus they do not provide a symmetric preconditioner.
3706 
3707    Level: developer
3708 
3709 .seealso: `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3710 @*/
3711 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x) {
3712   PetscFunctionBegin;
3713   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3714   PetscValidType(mat, 1);
3715   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3716   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3717   PetscCheckSameComm(mat, 1, b, 2);
3718   PetscCheckSameComm(mat, 1, x, 3);
3719   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3720   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);
3721   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);
3722   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);
3723   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3724   MatCheckPreallocated(mat, 1);
3725 
3726   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3727   PetscUseTypeMethod(mat, forwardsolve, b, x);
3728   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3729   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3730   PetscFunctionReturn(0);
3731 }
3732 
3733 /*@
3734    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3735                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3736 
3737    Neighbor-wise Collective on mat
3738 
3739    Input Parameters:
3740 +  mat - the factored matrix
3741 -  b - the right-hand-side vector
3742 
3743    Output Parameter:
3744 .  x - the result vector
3745 
3746    Notes:
3747    `MatSolve()` should be used for most applications, as it performs
3748    a forward solve followed by a backward solve.
3749 
3750    The vectors b and x cannot be the same.  I.e., one cannot
3751    call `MatBackwardSolve`(A,x,x).
3752 
3753    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3754    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3755    `MatForwardSolve()` solves U^T*D y = b, and
3756    `MatBackwardSolve()` solves U x = y.
3757    Thus they do not provide a symmetric preconditioner.
3758 
3759    Level: developer
3760 
3761 .seealso: `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3762 @*/
3763 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x) {
3764   PetscFunctionBegin;
3765   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3766   PetscValidType(mat, 1);
3767   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3768   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3769   PetscCheckSameComm(mat, 1, b, 2);
3770   PetscCheckSameComm(mat, 1, x, 3);
3771   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3772   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);
3773   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);
3774   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);
3775   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3776   MatCheckPreallocated(mat, 1);
3777 
3778   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3779   PetscUseTypeMethod(mat, backwardsolve, b, x);
3780   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3781   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3782   PetscFunctionReturn(0);
3783 }
3784 
3785 /*@
3786    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3787 
3788    Neighbor-wise Collective on mat
3789 
3790    Input Parameters:
3791 +  mat - the factored matrix
3792 .  b - the right-hand-side vector
3793 -  y - the vector to be added to
3794 
3795    Output Parameter:
3796 .  x - the result vector
3797 
3798    Note:
3799    The vectors b and x cannot be the same.  I.e., one cannot
3800    call `MatSolveAdd`(A,x,y,x).
3801 
3802    Level: developer
3803 
3804 .seealso: [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3805 @*/
3806 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x) {
3807   PetscScalar one = 1.0;
3808   Vec         tmp;
3809 
3810   PetscFunctionBegin;
3811   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3812   PetscValidType(mat, 1);
3813   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3814   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3815   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3816   PetscCheckSameComm(mat, 1, b, 2);
3817   PetscCheckSameComm(mat, 1, y, 3);
3818   PetscCheckSameComm(mat, 1, x, 4);
3819   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3820   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);
3821   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);
3822   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);
3823   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);
3824   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);
3825   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3826   MatCheckPreallocated(mat, 1);
3827 
3828   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3829   if (mat->factorerrortype) {
3830     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3831     PetscCall(VecSetInf(x));
3832   } else if (mat->ops->solveadd) {
3833     PetscUseTypeMethod(mat, solveadd, b, y, x);
3834   } else {
3835     /* do the solve then the add manually */
3836     if (x != y) {
3837       PetscCall(MatSolve(mat, b, x));
3838       PetscCall(VecAXPY(x, one, y));
3839     } else {
3840       PetscCall(VecDuplicate(x, &tmp));
3841       PetscCall(PetscLogObjectParent((PetscObject)mat, (PetscObject)tmp));
3842       PetscCall(VecCopy(x, tmp));
3843       PetscCall(MatSolve(mat, b, x));
3844       PetscCall(VecAXPY(x, one, tmp));
3845       PetscCall(VecDestroy(&tmp));
3846     }
3847   }
3848   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3849   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3850   PetscFunctionReturn(0);
3851 }
3852 
3853 /*@
3854    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3855 
3856    Neighbor-wise Collective on mat
3857 
3858    Input Parameters:
3859 +  mat - the factored matrix
3860 -  b - the right-hand-side vector
3861 
3862    Output Parameter:
3863 .  x - the result vector
3864 
3865    Notes:
3866    The vectors b and x cannot be the same.  I.e., one cannot
3867    call `MatSolveTranspose`(A,x,x).
3868 
3869    Most users should employ the `KSP` interface for linear solvers
3870    instead of working directly with matrix algebra routines such as this.
3871    See, e.g., `KSPCreate()`.
3872 
3873    Level: developer
3874 
3875 .seealso: `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3876 @*/
3877 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x) {
3878   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3879 
3880   PetscFunctionBegin;
3881   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3882   PetscValidType(mat, 1);
3883   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3884   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3885   PetscCheckSameComm(mat, 1, b, 2);
3886   PetscCheckSameComm(mat, 1, x, 3);
3887   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3888   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);
3889   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);
3890   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3891   MatCheckPreallocated(mat, 1);
3892   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3893   if (mat->factorerrortype) {
3894     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3895     PetscCall(VecSetInf(x));
3896   } else {
3897     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
3898     PetscCall((*f)(mat, b, x));
3899   }
3900   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
3901   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3902   PetscFunctionReturn(0);
3903 }
3904 
3905 /*@
3906    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
3907                       factored matrix.
3908 
3909    Neighbor-wise Collective on mat
3910 
3911    Input Parameters:
3912 +  mat - the factored matrix
3913 .  b - the right-hand-side vector
3914 -  y - the vector to be added to
3915 
3916    Output Parameter:
3917 .  x - the result vector
3918 
3919    Note:
3920    The vectors b and x cannot be the same.  I.e., one cannot
3921    call `MatSolveTransposeAdd`(A,x,y,x).
3922 
3923    Level: developer
3924 
3925 .seealso: `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
3926 @*/
3927 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x) {
3928   PetscScalar one = 1.0;
3929   Vec         tmp;
3930   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
3931 
3932   PetscFunctionBegin;
3933   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3934   PetscValidType(mat, 1);
3935   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3936   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3937   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3938   PetscCheckSameComm(mat, 1, b, 2);
3939   PetscCheckSameComm(mat, 1, y, 3);
3940   PetscCheckSameComm(mat, 1, x, 4);
3941   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3942   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);
3943   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);
3944   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);
3945   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);
3946   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
3947   MatCheckPreallocated(mat, 1);
3948 
3949   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
3950   if (mat->factorerrortype) {
3951     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3952     PetscCall(VecSetInf(x));
3953   } else if (f) {
3954     PetscCall((*f)(mat, b, y, x));
3955   } else {
3956     /* do the solve then the add manually */
3957     if (x != y) {
3958       PetscCall(MatSolveTranspose(mat, b, x));
3959       PetscCall(VecAXPY(x, one, y));
3960     } else {
3961       PetscCall(VecDuplicate(x, &tmp));
3962       PetscCall(PetscLogObjectParent((PetscObject)mat, (PetscObject)tmp));
3963       PetscCall(VecCopy(x, tmp));
3964       PetscCall(MatSolveTranspose(mat, b, x));
3965       PetscCall(VecAXPY(x, one, tmp));
3966       PetscCall(VecDestroy(&tmp));
3967     }
3968   }
3969   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
3970   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3971   PetscFunctionReturn(0);
3972 }
3973 /* ----------------------------------------------------------------*/
3974 
3975 /*@
3976    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
3977 
3978    Neighbor-wise Collective on mat
3979 
3980    Input Parameters:
3981 +  mat - the matrix
3982 .  b - the right hand side
3983 .  omega - the relaxation factor
3984 .  flag - flag indicating the type of SOR (see below)
3985 .  shift -  diagonal shift
3986 .  its - the number of iterations
3987 -  lits - the number of local iterations
3988 
3989    Output Parameter:
3990 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
3991 
3992    SOR Flags:
3993 +     `SOR_FORWARD_SWEEP` - forward SOR
3994 .     `SOR_BACKWARD_SWEEP` - backward SOR
3995 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
3996 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
3997 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
3998 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
3999 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4000 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4001          upper/lower triangular part of matrix to
4002          vector (with omega)
4003 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4004 
4005    Notes:
4006    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4007    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4008    on each processor.
4009 
4010    Application programmers will not generally use `MatSOR()` directly,
4011    but instead will employ the `KSP`/`PC` interface.
4012 
4013    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4014 
4015    Most users should employ the `KSP` interface for linear solvers
4016    instead of working directly with matrix algebra routines such as this.
4017    See, e.g., `KSPCreate()`.
4018 
4019    Vectors x and b CANNOT be the same
4020 
4021    Notes for Advanced Users:
4022    The flags are implemented as bitwise inclusive or operations.
4023    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4024    to specify a zero initial guess for SSOR.
4025 
4026    Developer Note:
4027    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4028 
4029    Level: developer
4030 
4031 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4032 @*/
4033 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x) {
4034   PetscFunctionBegin;
4035   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4036   PetscValidType(mat, 1);
4037   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4038   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4039   PetscCheckSameComm(mat, 1, b, 2);
4040   PetscCheckSameComm(mat, 1, x, 8);
4041   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4042   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4043   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);
4044   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);
4045   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);
4046   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4047   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4048   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4049 
4050   MatCheckPreallocated(mat, 1);
4051   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4052   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4053   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4054   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4055   PetscFunctionReturn(0);
4056 }
4057 
4058 /*
4059       Default matrix copy routine.
4060 */
4061 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str) {
4062   PetscInt           i, rstart = 0, rend = 0, nz;
4063   const PetscInt    *cwork;
4064   const PetscScalar *vwork;
4065 
4066   PetscFunctionBegin;
4067   if (B->assembled) PetscCall(MatZeroEntries(B));
4068   if (str == SAME_NONZERO_PATTERN) {
4069     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4070     for (i = rstart; i < rend; i++) {
4071       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4072       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4073       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4074     }
4075   } else {
4076     PetscCall(MatAYPX(B, 0.0, A, str));
4077   }
4078   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4079   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4080   PetscFunctionReturn(0);
4081 }
4082 
4083 /*@
4084    MatCopy - Copies a matrix to another matrix.
4085 
4086    Collective on A
4087 
4088    Input Parameters:
4089 +  A - the matrix
4090 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4091 
4092    Output Parameter:
4093 .  B - where the copy is put
4094 
4095    Notes:
4096    If you use `SAME_NONZERO_PATTERN `then the two matrices must have the same nonzero pattern or the routine will crash.
4097 
4098    `MatCopy()` copies the matrix entries of a matrix to another existing
4099    matrix (after first zeroing the second matrix).  A related routine is
4100    `MatConvert()`, which first creates a new matrix and then copies the data.
4101 
4102    Level: intermediate
4103 
4104 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4105 @*/
4106 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str) {
4107   PetscInt i;
4108 
4109   PetscFunctionBegin;
4110   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4111   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4112   PetscValidType(A, 1);
4113   PetscValidType(B, 2);
4114   PetscCheckSameComm(A, 1, B, 2);
4115   MatCheckPreallocated(B, 2);
4116   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4117   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4118   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,
4119              A->cmap->N, B->cmap->N);
4120   MatCheckPreallocated(A, 1);
4121   if (A == B) PetscFunctionReturn(0);
4122 
4123   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4124   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4125   else PetscCall(MatCopy_Basic(A, B, str));
4126 
4127   B->stencil.dim = A->stencil.dim;
4128   B->stencil.noc = A->stencil.noc;
4129   for (i = 0; i <= A->stencil.dim; i++) {
4130     B->stencil.dims[i]   = A->stencil.dims[i];
4131     B->stencil.starts[i] = A->stencil.starts[i];
4132   }
4133 
4134   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4135   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4136   PetscFunctionReturn(0);
4137 }
4138 
4139 /*@C
4140    MatConvert - Converts a matrix to another matrix, either of the same
4141    or different type.
4142 
4143    Collective on mat
4144 
4145    Input Parameters:
4146 +  mat - the matrix
4147 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4148    same type as the original matrix.
4149 -  reuse - denotes if the destination matrix is to be created or reused.
4150    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
4151    `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).
4152 
4153    Output Parameter:
4154 .  M - pointer to place new matrix
4155 
4156    Notes:
4157    `MatConvert()` first creates a new matrix and then copies the data from
4158    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4159    entries of one matrix to another already existing matrix context.
4160 
4161    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4162    the MPI communicator of the generated matrix is always the same as the communicator
4163    of the input matrix.
4164 
4165    Level: intermediate
4166 
4167 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4168 @*/
4169 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M) {
4170   PetscBool  sametype, issame, flg;
4171   PetscBool3 issymmetric, ishermitian;
4172   char       convname[256], mtype[256];
4173   Mat        B;
4174 
4175   PetscFunctionBegin;
4176   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4177   PetscValidType(mat, 1);
4178   PetscValidPointer(M, 4);
4179   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4180   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4181   MatCheckPreallocated(mat, 1);
4182 
4183   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4184   if (flg) newtype = mtype;
4185 
4186   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4187   PetscCall(PetscStrcmp(newtype, "same", &issame));
4188   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4189   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");
4190 
4191   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4192     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4193     PetscFunctionReturn(0);
4194   }
4195 
4196   /* Cache Mat options because some converters use MatHeaderReplace  */
4197   issymmetric = mat->symmetric;
4198   ishermitian = mat->hermitian;
4199 
4200   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4201     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4202     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4203   } else {
4204     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4205     const char *prefix[3]                                 = {"seq", "mpi", ""};
4206     PetscInt    i;
4207     /*
4208        Order of precedence:
4209        0) See if newtype is a superclass of the current matrix.
4210        1) See if a specialized converter is known to the current matrix.
4211        2) See if a specialized converter is known to the desired matrix class.
4212        3) See if a good general converter is registered for the desired class
4213           (as of 6/27/03 only MATMPIADJ falls into this category).
4214        4) See if a good general converter is known for the current matrix.
4215        5) Use a really basic converter.
4216     */
4217 
4218     /* 0) See if newtype is a superclass of the current matrix.
4219           i.e mat is mpiaij and newtype is aij */
4220     for (i = 0; i < 2; i++) {
4221       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4222       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4223       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4224       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4225       if (flg) {
4226         if (reuse == MAT_INPLACE_MATRIX) {
4227           PetscCall(PetscInfo(mat, "Early return\n"));
4228           PetscFunctionReturn(0);
4229         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4230           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4231           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4232           PetscFunctionReturn(0);
4233         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4234           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4235           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4236           PetscFunctionReturn(0);
4237         }
4238       }
4239     }
4240     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4241     for (i = 0; i < 3; i++) {
4242       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4243       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4244       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4245       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4246       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4247       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4248       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4249       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4250       if (conv) goto foundconv;
4251     }
4252 
4253     /* 2)  See if a specialized converter is known to the desired matrix class. */
4254     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4255     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4256     PetscCall(MatSetType(B, newtype));
4257     for (i = 0; i < 3; i++) {
4258       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4259       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4260       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4261       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4262       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4263       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4264       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4265       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4266       if (conv) {
4267         PetscCall(MatDestroy(&B));
4268         goto foundconv;
4269       }
4270     }
4271 
4272     /* 3) See if a good general converter is registered for the desired class */
4273     conv = B->ops->convertfrom;
4274     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4275     PetscCall(MatDestroy(&B));
4276     if (conv) goto foundconv;
4277 
4278     /* 4) See if a good general converter is known for the current matrix */
4279     if (mat->ops->convert) conv = mat->ops->convert;
4280     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4281     if (conv) goto foundconv;
4282 
4283     /* 5) Use a really basic converter. */
4284     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4285     conv = MatConvert_Basic;
4286 
4287   foundconv:
4288     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4289     PetscCall((*conv)(mat, newtype, reuse, M));
4290     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4291       /* the block sizes must be same if the mappings are copied over */
4292       (*M)->rmap->bs = mat->rmap->bs;
4293       (*M)->cmap->bs = mat->cmap->bs;
4294       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4295       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4296       (*M)->rmap->mapping = mat->rmap->mapping;
4297       (*M)->cmap->mapping = mat->cmap->mapping;
4298     }
4299     (*M)->stencil.dim = mat->stencil.dim;
4300     (*M)->stencil.noc = mat->stencil.noc;
4301     for (i = 0; i <= mat->stencil.dim; i++) {
4302       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4303       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4304     }
4305     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4306   }
4307   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4308 
4309   /* Copy Mat options */
4310   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4311   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4312   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4313   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4314   PetscFunctionReturn(0);
4315 }
4316 
4317 /*@C
4318    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4319 
4320    Not Collective
4321 
4322    Input Parameter:
4323 .  mat - the matrix, must be a factored matrix
4324 
4325    Output Parameter:
4326 .   type - the string name of the package (do not free this string)
4327 
4328    Note:
4329       In Fortran you pass in a empty string and the package name will be copied into it.
4330     (Make sure the string is long enough)
4331 
4332    Level: intermediate
4333 
4334 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4335 @*/
4336 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type) {
4337   PetscErrorCode (*conv)(Mat, MatSolverType *);
4338 
4339   PetscFunctionBegin;
4340   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4341   PetscValidType(mat, 1);
4342   PetscValidPointer(type, 2);
4343   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4344   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4345   if (conv) PetscCall((*conv)(mat, type));
4346   else *type = MATSOLVERPETSC;
4347   PetscFunctionReturn(0);
4348 }
4349 
4350 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4351 struct _MatSolverTypeForSpecifcType {
4352   MatType mtype;
4353   /* no entry for MAT_FACTOR_NONE */
4354   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4355   MatSolverTypeForSpecifcType next;
4356 };
4357 
4358 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4359 struct _MatSolverTypeHolder {
4360   char                       *name;
4361   MatSolverTypeForSpecifcType handlers;
4362   MatSolverTypeHolder         next;
4363 };
4364 
4365 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4366 
4367 /*@C
4368    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4369 
4370    Input Parameters:
4371 +    package - name of the package, for example petsc or superlu
4372 .    mtype - the matrix type that works with this package
4373 .    ftype - the type of factorization supported by the package
4374 -    createfactor - routine that will create the factored matrix ready to be used
4375 
4376     Level: developer
4377 
4378 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4379 @*/
4380 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *)) {
4381   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4382   PetscBool                   flg;
4383   MatSolverTypeForSpecifcType inext, iprev = NULL;
4384 
4385   PetscFunctionBegin;
4386   PetscCall(MatInitializePackage());
4387   if (!next) {
4388     PetscCall(PetscNew(&MatSolverTypeHolders));
4389     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4390     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4391     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4392     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4393     PetscFunctionReturn(0);
4394   }
4395   while (next) {
4396     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4397     if (flg) {
4398       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4399       inext = next->handlers;
4400       while (inext) {
4401         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4402         if (flg) {
4403           inext->createfactor[(int)ftype - 1] = createfactor;
4404           PetscFunctionReturn(0);
4405         }
4406         iprev = inext;
4407         inext = inext->next;
4408       }
4409       PetscCall(PetscNew(&iprev->next));
4410       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4411       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4412       PetscFunctionReturn(0);
4413     }
4414     prev = next;
4415     next = next->next;
4416   }
4417   PetscCall(PetscNew(&prev->next));
4418   PetscCall(PetscStrallocpy(package, &prev->next->name));
4419   PetscCall(PetscNew(&prev->next->handlers));
4420   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4421   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4422   PetscFunctionReturn(0);
4423 }
4424 
4425 /*@C
4426    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4427 
4428    Input Parameters:
4429 +    type - name of the package, for example petsc or superlu
4430 .    ftype - the type of factorization supported by the type
4431 -    mtype - the matrix type that works with this type
4432 
4433    Output Parameters:
4434 +   foundtype - `PETSC_TRUE` if the type was registered
4435 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4436 -   createfactor - routine that will create the factored matrix ready to be used or NULL if not found
4437 
4438     Level: developer
4439 
4440 .seealso: `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4441 @*/
4442 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *)) {
4443   MatSolverTypeHolder         next = MatSolverTypeHolders;
4444   PetscBool                   flg;
4445   MatSolverTypeForSpecifcType inext;
4446 
4447   PetscFunctionBegin;
4448   if (foundtype) *foundtype = PETSC_FALSE;
4449   if (foundmtype) *foundmtype = PETSC_FALSE;
4450   if (createfactor) *createfactor = NULL;
4451 
4452   if (type) {
4453     while (next) {
4454       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4455       if (flg) {
4456         if (foundtype) *foundtype = PETSC_TRUE;
4457         inext = next->handlers;
4458         while (inext) {
4459           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4460           if (flg) {
4461             if (foundmtype) *foundmtype = PETSC_TRUE;
4462             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4463             PetscFunctionReturn(0);
4464           }
4465           inext = inext->next;
4466         }
4467       }
4468       next = next->next;
4469     }
4470   } else {
4471     while (next) {
4472       inext = next->handlers;
4473       while (inext) {
4474         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4475         if (flg && inext->createfactor[(int)ftype - 1]) {
4476           if (foundtype) *foundtype = PETSC_TRUE;
4477           if (foundmtype) *foundmtype = PETSC_TRUE;
4478           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4479           PetscFunctionReturn(0);
4480         }
4481         inext = inext->next;
4482       }
4483       next = next->next;
4484     }
4485     /* try with base classes inext->mtype */
4486     next = MatSolverTypeHolders;
4487     while (next) {
4488       inext = next->handlers;
4489       while (inext) {
4490         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4491         if (flg && inext->createfactor[(int)ftype - 1]) {
4492           if (foundtype) *foundtype = PETSC_TRUE;
4493           if (foundmtype) *foundmtype = PETSC_TRUE;
4494           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4495           PetscFunctionReturn(0);
4496         }
4497         inext = inext->next;
4498       }
4499       next = next->next;
4500     }
4501   }
4502   PetscFunctionReturn(0);
4503 }
4504 
4505 PetscErrorCode MatSolverTypeDestroy(void) {
4506   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4507   MatSolverTypeForSpecifcType inext, iprev;
4508 
4509   PetscFunctionBegin;
4510   while (next) {
4511     PetscCall(PetscFree(next->name));
4512     inext = next->handlers;
4513     while (inext) {
4514       PetscCall(PetscFree(inext->mtype));
4515       iprev = inext;
4516       inext = inext->next;
4517       PetscCall(PetscFree(iprev));
4518     }
4519     prev = next;
4520     next = next->next;
4521     PetscCall(PetscFree(prev));
4522   }
4523   MatSolverTypeHolders = NULL;
4524   PetscFunctionReturn(0);
4525 }
4526 
4527 /*@C
4528    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4529 
4530    Logically Collective on mat
4531 
4532    Input Parameters:
4533 .  mat - the matrix
4534 
4535    Output Parameters:
4536 .  flg - `PETSC_TRUE` if uses the ordering
4537 
4538    Note:
4539    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4540    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4541 
4542    Level: developer
4543 
4544 .seealso: [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4545 @*/
4546 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg) {
4547   PetscFunctionBegin;
4548   *flg = mat->canuseordering;
4549   PetscFunctionReturn(0);
4550 }
4551 
4552 /*@C
4553    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4554 
4555    Logically Collective on mat
4556 
4557    Input Parameters:
4558 .  mat - the matrix obtained with `MatGetFactor()`
4559 
4560    Output Parameters:
4561 .  otype - the preferred type
4562 
4563    Level: developer
4564 
4565 .seealso: [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4566 @*/
4567 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype) {
4568   PetscFunctionBegin;
4569   *otype = mat->preferredordering[ftype];
4570   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4571   PetscFunctionReturn(0);
4572 }
4573 
4574 /*@C
4575    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4576 
4577    Collective on mat
4578 
4579    Input Parameters:
4580 +  mat - the matrix
4581 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4582 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4583 
4584    Output Parameters:
4585 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4586 
4587    Options Database Key:
4588 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4589                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4590 
4591    Notes:
4592      Users usually access the factorization solvers via `KSP`
4593 
4594       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4595      such as pastix, superlu, mumps etc.
4596 
4597       PETSc must have been ./configure to use the external solver, using the option --download-package
4598 
4599       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4600       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4601       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4602 
4603    Developer Note:
4604       This should actually be called `MatCreateFactor()` since it creates a new factor object
4605 
4606    Level: intermediate
4607 
4608 .seealso: [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4609           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4610 @*/
4611 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f) {
4612   PetscBool foundtype, foundmtype;
4613   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4614 
4615   PetscFunctionBegin;
4616   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4617   PetscValidType(mat, 1);
4618 
4619   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4620   MatCheckPreallocated(mat, 1);
4621 
4622   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4623   if (!foundtype) {
4624     if (type) {
4625       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],
4626               ((PetscObject)mat)->type_name, type);
4627     } else {
4628       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);
4629     }
4630   }
4631   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4632   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);
4633 
4634   PetscCall((*conv)(mat, ftype, f));
4635   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4636   PetscFunctionReturn(0);
4637 }
4638 
4639 /*@C
4640    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4641 
4642    Not Collective
4643 
4644    Input Parameters:
4645 +  mat - the matrix
4646 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4647 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4648 
4649    Output Parameter:
4650 .    flg - PETSC_TRUE if the factorization is available
4651 
4652    Notes:
4653       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4654      such as pastix, superlu, mumps etc.
4655 
4656       PETSc must have been ./configure to use the external solver, using the option --download-package
4657 
4658    Developer Note:
4659       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4660 
4661    Level: intermediate
4662 
4663 .seealso: [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4664           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4665 @*/
4666 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg) {
4667   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4668 
4669   PetscFunctionBegin;
4670   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4671   PetscValidType(mat, 1);
4672   PetscValidBoolPointer(flg, 4);
4673 
4674   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4675   MatCheckPreallocated(mat, 1);
4676 
4677   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4678   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4679   PetscFunctionReturn(0);
4680 }
4681 
4682 /*@
4683    MatDuplicate - Duplicates a matrix including the non-zero structure.
4684 
4685    Collective on mat
4686 
4687    Input Parameters:
4688 +  mat - the matrix
4689 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4690         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4691 
4692    Output Parameter:
4693 .  M - pointer to place new matrix
4694 
4695    Level: intermediate
4696 
4697    Notes:
4698     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4699 
4700     May be called with an unassembled input `Mat` if `MAT_DO_NOT_COPY_VALUES` is used, in which case the output `Mat` is unassembled as well.
4701 
4702     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
4703     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4704     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4705 
4706 .seealso: `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4707 @*/
4708 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M) {
4709   Mat         B;
4710   VecType     vtype;
4711   PetscInt    i;
4712   PetscObject dm;
4713   void (*viewf)(void);
4714 
4715   PetscFunctionBegin;
4716   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4717   PetscValidType(mat, 1);
4718   PetscValidPointer(M, 3);
4719   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4720   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4721   MatCheckPreallocated(mat, 1);
4722 
4723   *M = NULL;
4724   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4725   PetscUseTypeMethod(mat, duplicate, op, M);
4726   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4727   B = *M;
4728 
4729   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4730   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4731   PetscCall(MatGetVecType(mat, &vtype));
4732   PetscCall(MatSetVecType(B, vtype));
4733 
4734   B->stencil.dim = mat->stencil.dim;
4735   B->stencil.noc = mat->stencil.noc;
4736   for (i = 0; i <= mat->stencil.dim; i++) {
4737     B->stencil.dims[i]   = mat->stencil.dims[i];
4738     B->stencil.starts[i] = mat->stencil.starts[i];
4739   }
4740 
4741   B->nooffproczerorows = mat->nooffproczerorows;
4742   B->nooffprocentries  = mat->nooffprocentries;
4743 
4744   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4745   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4746   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4747   PetscFunctionReturn(0);
4748 }
4749 
4750 /*@
4751    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4752 
4753    Logically Collective on mat
4754 
4755    Input Parameters:
4756 +  mat - the matrix
4757 -  v - the vector for storing the diagonal
4758 
4759    Output Parameter:
4760 .  v - the diagonal of the matrix
4761 
4762    Level: intermediate
4763 
4764    Note:
4765    Currently only correct in parallel for square matrices.
4766 
4767 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4768 @*/
4769 PetscErrorCode MatGetDiagonal(Mat mat, Vec v) {
4770   PetscFunctionBegin;
4771   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4772   PetscValidType(mat, 1);
4773   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4774   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4775   MatCheckPreallocated(mat, 1);
4776 
4777   PetscUseTypeMethod(mat, getdiagonal, v);
4778   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4779   PetscFunctionReturn(0);
4780 }
4781 
4782 /*@C
4783    MatGetRowMin - Gets the minimum value (of the real part) of each
4784         row of the matrix
4785 
4786    Logically Collective on mat
4787 
4788    Input Parameter:
4789 .  mat - the matrix
4790 
4791    Output Parameters:
4792 +  v - the vector for storing the maximums
4793 -  idx - the indices of the column found for each row (optional)
4794 
4795    Level: intermediate
4796 
4797    Note:
4798     The result of this call are the same as if one converted the matrix to dense format
4799       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4800 
4801     This code is only implemented for a couple of matrix formats.
4802 
4803 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4804           `MatGetRowMax()`
4805 @*/
4806 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[]) {
4807   PetscFunctionBegin;
4808   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4809   PetscValidType(mat, 1);
4810   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4811   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4812 
4813   if (!mat->cmap->N) {
4814     PetscCall(VecSet(v, PETSC_MAX_REAL));
4815     if (idx) {
4816       PetscInt i, m = mat->rmap->n;
4817       for (i = 0; i < m; i++) idx[i] = -1;
4818     }
4819   } else {
4820     MatCheckPreallocated(mat, 1);
4821   }
4822   PetscUseTypeMethod(mat, getrowmin, v, idx);
4823   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4824   PetscFunctionReturn(0);
4825 }
4826 
4827 /*@C
4828    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4829         row of the matrix
4830 
4831    Logically Collective on mat
4832 
4833    Input Parameter:
4834 .  mat - the matrix
4835 
4836    Output Parameters:
4837 +  v - the vector for storing the minimums
4838 -  idx - the indices of the column found for each row (or NULL if not needed)
4839 
4840    Level: intermediate
4841 
4842    Notes:
4843     if a row is completely empty or has only 0.0 values then the idx[] value for that
4844     row is 0 (the first column).
4845 
4846     This code is only implemented for a couple of matrix formats.
4847 
4848 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4849 @*/
4850 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[]) {
4851   PetscFunctionBegin;
4852   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4853   PetscValidType(mat, 1);
4854   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4855   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4856   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4857 
4858   if (!mat->cmap->N) {
4859     PetscCall(VecSet(v, 0.0));
4860     if (idx) {
4861       PetscInt i, m = mat->rmap->n;
4862       for (i = 0; i < m; i++) idx[i] = -1;
4863     }
4864   } else {
4865     MatCheckPreallocated(mat, 1);
4866     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4867     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4868   }
4869   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4870   PetscFunctionReturn(0);
4871 }
4872 
4873 /*@C
4874    MatGetRowMax - Gets the maximum value (of the real part) of each
4875         row of the matrix
4876 
4877    Logically Collective on mat
4878 
4879    Input Parameter:
4880 .  mat - the matrix
4881 
4882    Output Parameters:
4883 +  v - the vector for storing the maximums
4884 -  idx - the indices of the column found for each row (optional)
4885 
4886    Level: intermediate
4887 
4888    Notes:
4889     The result of this call are the same as if one converted the matrix to dense format
4890       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4891 
4892     This code is only implemented for a couple of matrix formats.
4893 
4894 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4895 @*/
4896 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[]) {
4897   PetscFunctionBegin;
4898   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4899   PetscValidType(mat, 1);
4900   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4901   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4902 
4903   if (!mat->cmap->N) {
4904     PetscCall(VecSet(v, PETSC_MIN_REAL));
4905     if (idx) {
4906       PetscInt i, m = mat->rmap->n;
4907       for (i = 0; i < m; i++) idx[i] = -1;
4908     }
4909   } else {
4910     MatCheckPreallocated(mat, 1);
4911     PetscUseTypeMethod(mat, getrowmax, v, idx);
4912   }
4913   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4914   PetscFunctionReturn(0);
4915 }
4916 
4917 /*@C
4918    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
4919         row of the matrix
4920 
4921    Logically Collective on mat
4922 
4923    Input Parameter:
4924 .  mat - the matrix
4925 
4926    Output Parameters:
4927 +  v - the vector for storing the maximums
4928 -  idx - the indices of the column found for each row (or NULL if not needed)
4929 
4930    Level: intermediate
4931 
4932    Notes:
4933     if a row is completely empty or has only 0.0 values then the idx[] value for that
4934     row is 0 (the first column).
4935 
4936     This code is only implemented for a couple of matrix formats.
4937 
4938 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
4939 @*/
4940 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[]) {
4941   PetscFunctionBegin;
4942   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4943   PetscValidType(mat, 1);
4944   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4945   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4946 
4947   if (!mat->cmap->N) {
4948     PetscCall(VecSet(v, 0.0));
4949     if (idx) {
4950       PetscInt i, m = mat->rmap->n;
4951       for (i = 0; i < m; i++) idx[i] = -1;
4952     }
4953   } else {
4954     MatCheckPreallocated(mat, 1);
4955     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4956     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
4957   }
4958   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4959   PetscFunctionReturn(0);
4960 }
4961 
4962 /*@
4963    MatGetRowSum - Gets the sum of each row of the matrix
4964 
4965    Logically or Neighborhood Collective on mat
4966 
4967    Input Parameters:
4968 .  mat - the matrix
4969 
4970    Output Parameter:
4971 .  v - the vector for storing the sum of rows
4972 
4973    Level: intermediate
4974 
4975    Notes:
4976     This code is slow since it is not currently specialized for different formats
4977 
4978 .seealso: `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
4979 @*/
4980 PetscErrorCode MatGetRowSum(Mat mat, Vec v) {
4981   Vec ones;
4982 
4983   PetscFunctionBegin;
4984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4985   PetscValidType(mat, 1);
4986   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4987   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4988   MatCheckPreallocated(mat, 1);
4989   PetscCall(MatCreateVecs(mat, &ones, NULL));
4990   PetscCall(VecSet(ones, 1.));
4991   PetscCall(MatMult(mat, ones, v));
4992   PetscCall(VecDestroy(&ones));
4993   PetscFunctionReturn(0);
4994 }
4995 
4996 /*@
4997    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
4998    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
4999 
5000    Collective on mat
5001 
5002    Input Parameter:
5003 .  mat - the matrix to provide the transpose
5004 
5005    Output Parameter:
5006 .  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
5007 
5008    Level: advanced
5009 
5010    Note:
5011    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
5012    routine allows bypassing that call.
5013 
5014 .seealso: `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5015 @*/
5016 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B) {
5017   PetscContainer  rB = NULL;
5018   MatParentState *rb = NULL;
5019 
5020   PetscFunctionBegin;
5021   PetscCall(PetscNew(&rb));
5022   rb->id    = ((PetscObject)mat)->id;
5023   rb->state = 0;
5024   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5025   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5026   PetscCall(PetscContainerSetPointer(rB, rb));
5027   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5028   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5029   PetscCall(PetscObjectDereference((PetscObject)rB));
5030   PetscFunctionReturn(0);
5031 }
5032 
5033 /*@
5034    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5035 
5036    Collective on mat
5037 
5038    Input Parameters:
5039 +  mat - the matrix to transpose
5040 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5041 
5042    Output Parameter:
5043 .  B - the transpose
5044 
5045    Notes:
5046      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5047 
5048      `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
5049      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5050 
5051      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.
5052 
5053      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5054 
5055      If mat is unchanged from the last call this function returns immediately without recomputing the result
5056 
5057      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5058 
5059    Level: intermediate
5060 
5061 .seealso: `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5062           `MatTransposeSymbolic()`
5063 @*/
5064 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B) {
5065   PetscContainer  rB = NULL;
5066   MatParentState *rb = NULL;
5067 
5068   PetscFunctionBegin;
5069   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5070   PetscValidType(mat, 1);
5071   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5072   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5073   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5074   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5075   MatCheckPreallocated(mat, 1);
5076   if (reuse == MAT_REUSE_MATRIX) {
5077     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5078     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5079     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5080     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5081     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(0);
5082   }
5083 
5084   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5085   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5086     PetscUseTypeMethod(mat, transpose, reuse, B);
5087     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5088   }
5089   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5090 
5091   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5092   if (reuse != MAT_INPLACE_MATRIX) {
5093     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5094     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5095     rb->state        = ((PetscObject)mat)->state;
5096     rb->nonzerostate = mat->nonzerostate;
5097   }
5098   PetscFunctionReturn(0);
5099 }
5100 
5101 /*@
5102    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5103 
5104    Collective on A
5105 
5106    Input Parameters:
5107 .  A - the matrix to transpose
5108 
5109    Output Parameter:
5110 .  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
5111       numerical portion.
5112 
5113    Level: intermediate
5114 
5115    Note:
5116    This is not supported for many matrix types, use `MatTranspose()` in those cases
5117 
5118 .seealso: `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5119 @*/
5120 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B) {
5121   PetscFunctionBegin;
5122   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5123   PetscValidType(A, 1);
5124   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5125   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5126   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5127   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5128   PetscCall((*A->ops->transposesymbolic)(A, B));
5129   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5130 
5131   PetscCall(MatTransposeSetPrecursor(A, *B));
5132   PetscFunctionReturn(0);
5133 }
5134 
5135 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B) {
5136   PetscContainer  rB;
5137   MatParentState *rb;
5138 
5139   PetscFunctionBegin;
5140   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5141   PetscValidType(A, 1);
5142   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5143   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5144   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5145   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5146   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5147   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5148   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5149   PetscFunctionReturn(0);
5150 }
5151 
5152 /*@
5153    MatIsTranspose - Test whether a matrix is another one's transpose,
5154         or its own, in which case it tests symmetry.
5155 
5156    Collective on A
5157 
5158    Input Parameters:
5159 +  A - the matrix to test
5160 -  B - the matrix to test against, this can equal the first parameter
5161 
5162    Output Parameters:
5163 .  flg - the result
5164 
5165    Notes:
5166    Only available for `MATAIJ` matrices.
5167 
5168    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5169    test involves parallel copies of the block-offdiagonal parts of the matrix.
5170 
5171    Level: intermediate
5172 
5173 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5174 @*/
5175 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) {
5176   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5177 
5178   PetscFunctionBegin;
5179   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5180   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5181   PetscValidBoolPointer(flg, 4);
5182   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5183   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5184   *flg = PETSC_FALSE;
5185   if (f && g) {
5186     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5187     PetscCall((*f)(A, B, tol, flg));
5188   } else {
5189     MatType mattype;
5190 
5191     PetscCall(MatGetType(f ? B : A, &mattype));
5192     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5193   }
5194   PetscFunctionReturn(0);
5195 }
5196 
5197 /*@
5198    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5199 
5200    Collective on mat
5201 
5202    Input Parameters:
5203 +  mat - the matrix to transpose and complex conjugate
5204 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5205 
5206    Output Parameter:
5207 .  B - the Hermitian transpose
5208 
5209    Level: intermediate
5210 
5211 .seealso: `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5212 @*/
5213 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B) {
5214   PetscFunctionBegin;
5215   PetscCall(MatTranspose(mat, reuse, B));
5216 #if defined(PETSC_USE_COMPLEX)
5217   PetscCall(MatConjugate(*B));
5218 #endif
5219   PetscFunctionReturn(0);
5220 }
5221 
5222 /*@
5223    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5224 
5225    Collective on A
5226 
5227    Input Parameters:
5228 +  A - the matrix to test
5229 -  B - the matrix to test against, this can equal the first parameter
5230 
5231    Output Parameters:
5232 .  flg - the result
5233 
5234    Notes:
5235    Only available for `MATAIJ` matrices.
5236 
5237    The sequential algorithm
5238    has a running time of the order of the number of nonzeros; the parallel
5239    test involves parallel copies of the block-offdiagonal parts of the matrix.
5240 
5241    Level: intermediate
5242 
5243 .seealso: `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5244 @*/
5245 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg) {
5246   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5247 
5248   PetscFunctionBegin;
5249   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5250   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5251   PetscValidBoolPointer(flg, 4);
5252   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5253   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5254   if (f && g) {
5255     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5256     PetscCall((*f)(A, B, tol, flg));
5257   }
5258   PetscFunctionReturn(0);
5259 }
5260 
5261 /*@
5262    MatPermute - Creates a new matrix with rows and columns permuted from the
5263    original.
5264 
5265    Collective on mat
5266 
5267    Input Parameters:
5268 +  mat - the matrix to permute
5269 .  row - row permutation, each processor supplies only the permutation for its rows
5270 -  col - column permutation, each processor supplies only the permutation for its columns
5271 
5272    Output Parameters:
5273 .  B - the permuted matrix
5274 
5275    Level: advanced
5276 
5277    Note:
5278    The index sets map from row/col of permuted matrix to row/col of original matrix.
5279    The index sets should be on the same communicator as mat and have the same local sizes.
5280 
5281    Developer Note:
5282      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5283      exploit the fact that row and col are permutations, consider implementing the
5284      more general `MatCreateSubMatrix()` instead.
5285 
5286 .seealso: `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5287 @*/
5288 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B) {
5289   PetscFunctionBegin;
5290   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5291   PetscValidType(mat, 1);
5292   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5293   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5294   PetscValidPointer(B, 4);
5295   PetscCheckSameComm(mat, 1, row, 2);
5296   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5297   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5298   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5299   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5300   MatCheckPreallocated(mat, 1);
5301 
5302   if (mat->ops->permute) {
5303     PetscUseTypeMethod(mat, permute, row, col, B);
5304     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5305   } else {
5306     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5307   }
5308   PetscFunctionReturn(0);
5309 }
5310 
5311 /*@
5312    MatEqual - Compares two matrices.
5313 
5314    Collective on A
5315 
5316    Input Parameters:
5317 +  A - the first matrix
5318 -  B - the second matrix
5319 
5320    Output Parameter:
5321 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5322 
5323    Level: intermediate
5324 
5325 .seealso: `Mat`
5326 @*/
5327 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg) {
5328   PetscFunctionBegin;
5329   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5330   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5331   PetscValidType(A, 1);
5332   PetscValidType(B, 2);
5333   PetscValidBoolPointer(flg, 3);
5334   PetscCheckSameComm(A, 1, B, 2);
5335   MatCheckPreallocated(A, 1);
5336   MatCheckPreallocated(B, 2);
5337   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5338   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5339   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,
5340              B->cmap->N);
5341   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5342     PetscUseTypeMethod(A, equal, B, flg);
5343   } else {
5344     PetscCall(MatMultEqual(A, B, 10, flg));
5345   }
5346   PetscFunctionReturn(0);
5347 }
5348 
5349 /*@
5350    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5351    matrices that are stored as vectors.  Either of the two scaling
5352    matrices can be NULL.
5353 
5354    Collective on mat
5355 
5356    Input Parameters:
5357 +  mat - the matrix to be scaled
5358 .  l - the left scaling vector (or NULL)
5359 -  r - the right scaling vector (or NULL)
5360 
5361    Note:
5362    `MatDiagonalScale()` computes A = LAR, where
5363    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5364    The L scales the rows of the matrix, the R scales the columns of the matrix.
5365 
5366    Level: intermediate
5367 
5368 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5369 @*/
5370 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r) {
5371   PetscFunctionBegin;
5372   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5373   PetscValidType(mat, 1);
5374   if (l) {
5375     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5376     PetscCheckSameComm(mat, 1, l, 2);
5377   }
5378   if (r) {
5379     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5380     PetscCheckSameComm(mat, 1, r, 3);
5381   }
5382   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5383   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5384   MatCheckPreallocated(mat, 1);
5385   if (!l && !r) PetscFunctionReturn(0);
5386 
5387   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5388   PetscUseTypeMethod(mat, diagonalscale, l, r);
5389   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5390   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5391   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5392   PetscFunctionReturn(0);
5393 }
5394 
5395 /*@
5396     MatScale - Scales all elements of a matrix by a given number.
5397 
5398     Logically Collective on mat
5399 
5400     Input Parameters:
5401 +   mat - the matrix to be scaled
5402 -   a  - the scaling value
5403 
5404     Output Parameter:
5405 .   mat - the scaled matrix
5406 
5407     Level: intermediate
5408 
5409 .seealso: `Mat`, `MatDiagonalScale()`
5410 @*/
5411 PetscErrorCode MatScale(Mat mat, PetscScalar a) {
5412   PetscFunctionBegin;
5413   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5414   PetscValidType(mat, 1);
5415   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5416   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5417   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5418   PetscValidLogicalCollectiveScalar(mat, a, 2);
5419   MatCheckPreallocated(mat, 1);
5420 
5421   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5422   if (a != (PetscScalar)1.0) {
5423     PetscUseTypeMethod(mat, scale, a);
5424     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5425   }
5426   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5427   PetscFunctionReturn(0);
5428 }
5429 
5430 /*@
5431    MatNorm - Calculates various norms of a matrix.
5432 
5433    Collective on mat
5434 
5435    Input Parameters:
5436 +  mat - the matrix
5437 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5438 
5439    Output Parameter:
5440 .  nrm - the resulting norm
5441 
5442    Level: intermediate
5443 
5444 .seealso: `Mat`
5445 @*/
5446 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm) {
5447   PetscFunctionBegin;
5448   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5449   PetscValidType(mat, 1);
5450   PetscValidRealPointer(nrm, 3);
5451 
5452   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5453   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5454   MatCheckPreallocated(mat, 1);
5455 
5456   PetscUseTypeMethod(mat, norm, type, nrm);
5457   PetscFunctionReturn(0);
5458 }
5459 
5460 /*
5461      This variable is used to prevent counting of MatAssemblyBegin() that
5462    are called from within a MatAssemblyEnd().
5463 */
5464 static PetscInt MatAssemblyEnd_InUse = 0;
5465 /*@
5466    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5467    be called after completing all calls to `MatSetValues()`.
5468 
5469    Collective on mat
5470 
5471    Input Parameters:
5472 +  mat - the matrix
5473 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5474 
5475    Notes:
5476    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5477    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5478 
5479    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5480    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5481    using the matrix.
5482 
5483    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5484    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
5485    a global collective operation requring all processes that share the matrix.
5486 
5487    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5488    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5489    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5490 
5491    Level: beginner
5492 
5493 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5494 @*/
5495 PetscErrorCode  MatAssemblyBegin(Mat mat, MatAssemblyType type) {
5496    PetscFunctionBegin;
5497    PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5498    PetscValidType(mat, 1);
5499    MatCheckPreallocated(mat, 1);
5500    PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5501    if (mat->assembled) {
5502      mat->was_assembled = PETSC_TRUE;
5503      mat->assembled     = PETSC_FALSE;
5504   }
5505 
5506    if (!MatAssemblyEnd_InUse) {
5507      PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5508      PetscTryTypeMethod(mat, assemblybegin, type);
5509      PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5510   } else PetscTryTypeMethod(mat, assemblybegin, type);
5511    PetscFunctionReturn(0);
5512 }
5513 
5514 /*@
5515    MatAssembled - Indicates if a matrix has been assembled and is ready for
5516      use; for example, in matrix-vector product.
5517 
5518    Not Collective
5519 
5520    Input Parameter:
5521 .  mat - the matrix
5522 
5523    Output Parameter:
5524 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5525 
5526    Level: advanced
5527 
5528 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5529 @*/
5530 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled) {
5531   PetscFunctionBegin;
5532   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5533   PetscValidBoolPointer(assembled, 2);
5534   *assembled = mat->assembled;
5535   PetscFunctionReturn(0);
5536 }
5537 
5538 /*@
5539    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5540    be called after `MatAssemblyBegin()`.
5541 
5542    Collective on Mat
5543 
5544    Input Parameters:
5545 +  mat - the matrix
5546 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5547 
5548    Options Database Keys:
5549 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5550 .  -mat_view ::ascii_info_detail - Prints more detailed info
5551 .  -mat_view - Prints matrix in ASCII format
5552 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5553 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5554 .  -display <name> - Sets display name (default is host)
5555 .  -draw_pause <sec> - Sets number of seconds to pause after display
5556 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5557 .  -viewer_socket_machine <machine> - Machine to use for socket
5558 .  -viewer_socket_port <port> - Port number to use for socket
5559 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5560 
5561    Level: beginner
5562 
5563 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5564 @*/
5565 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type) {
5566   static PetscInt inassm = 0;
5567   PetscBool       flg    = PETSC_FALSE;
5568 
5569   PetscFunctionBegin;
5570   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5571   PetscValidType(mat, 1);
5572 
5573   inassm++;
5574   MatAssemblyEnd_InUse++;
5575   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5576     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5577     PetscTryTypeMethod(mat, assemblyend, type);
5578     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5579   } else PetscTryTypeMethod(mat, assemblyend, type);
5580 
5581   /* Flush assembly is not a true assembly */
5582   if (type != MAT_FLUSH_ASSEMBLY) {
5583     if (mat->num_ass) {
5584       if (!mat->symmetry_eternal) {
5585         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5586         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5587       }
5588       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5589       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5590     }
5591     mat->num_ass++;
5592     mat->assembled        = PETSC_TRUE;
5593     mat->ass_nonzerostate = mat->nonzerostate;
5594   }
5595 
5596   mat->insertmode = NOT_SET_VALUES;
5597   MatAssemblyEnd_InUse--;
5598   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5599   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5600     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5601 
5602     if (mat->checksymmetryonassembly) {
5603       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5604       if (flg) {
5605         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5606       } else {
5607         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5608       }
5609     }
5610     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5611   }
5612   inassm--;
5613   PetscFunctionReturn(0);
5614 }
5615 
5616 /*@
5617    MatSetOption - Sets a parameter option for a matrix. Some options
5618    may be specific to certain storage formats.  Some options
5619    determine how values will be inserted (or added). Sorted,
5620    row-oriented input will generally assemble the fastest. The default
5621    is row-oriented.
5622 
5623    Logically Collective on mat for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5624 
5625    Input Parameters:
5626 +  mat - the matrix
5627 .  option - the option, one of those listed below (and possibly others),
5628 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5629 
5630   Options Describing Matrix Structure:
5631 +    `MAT_SPD` - symmetric positive definite
5632 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5633 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5634 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5635 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5636 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5637 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5638 
5639    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5640    do not need to be computed (usually at a high cost)
5641 
5642    Options For Use with `MatSetValues()`:
5643    Insert a logically dense subblock, which can be
5644 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5645 
5646    Note these options reflect the data you pass in with `MatSetValues()`; it has
5647    nothing to do with how the data is stored internally in the matrix
5648    data structure.
5649 
5650    When (re)assembling a matrix, we can restrict the input for
5651    efficiency/debugging purposes.  These options include
5652 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5653 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5654 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5655 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5656 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5657 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5658         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5659         performance for very large process counts.
5660 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5661         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5662         functions, instead sending only neighbor messages.
5663 
5664    Notes:
5665    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5666 
5667    Some options are relevant only for particular matrix types and
5668    are thus ignored by others.  Other options are not supported by
5669    certain matrix types and will generate an error message if set.
5670 
5671    If using a Fortran 77 module to compute a matrix, one may need to
5672    use the column-oriented option (or convert to the row-oriented
5673    format).
5674 
5675    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5676    that would generate a new entry in the nonzero structure is instead
5677    ignored.  Thus, if memory has not alredy been allocated for this particular
5678    data, then the insertion is ignored. For dense matrices, in which
5679    the entire array is allocated, no entries are ever ignored.
5680    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5681 
5682    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5683    that would generate a new entry in the nonzero structure instead produces
5684    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
5685 
5686    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5687    that would generate a new entry that has not been preallocated will
5688    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5689    only.) This is a useful flag when debugging matrix memory preallocation.
5690    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5691 
5692    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5693    other processors should be dropped, rather than stashed.
5694    This is useful if you know that the "owning" processor is also
5695    always generating the correct matrix entries, so that PETSc need
5696    not transfer duplicate entries generated on another processor.
5697 
5698    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5699    searches during matrix assembly. When this flag is set, the hash table
5700    is created during the first matrix assembly. This hash table is
5701    used the next time through, during `MatSetVaules()`/`MatSetVaulesBlocked()`
5702    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5703    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5704    supported by` MATMPIBAIJ` format only.
5705 
5706    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5707    are kept in the nonzero structure
5708 
5709    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5710    a zero location in the matrix
5711 
5712    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5713 
5714    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5715         zero row routines and thus improves performance for very large process counts.
5716 
5717    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5718         part of the matrix (since they should match the upper triangular part).
5719 
5720    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5721                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5722                      with finite difference schemes with non-periodic boundary conditions.
5723 
5724    Developer Note:
5725    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5726    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5727    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5728    not changed.
5729 
5730    Level: intermediate
5731 
5732 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5733 @*/
5734 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg) {
5735   PetscFunctionBegin;
5736   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5737   if (op > 0) {
5738     PetscValidLogicalCollectiveEnum(mat, op, 2);
5739     PetscValidLogicalCollectiveBool(mat, flg, 3);
5740   }
5741 
5742   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);
5743 
5744   switch (op) {
5745   case MAT_FORCE_DIAGONAL_ENTRIES: mat->force_diagonals = flg; PetscFunctionReturn(0);
5746   case MAT_NO_OFF_PROC_ENTRIES: mat->nooffprocentries = flg; PetscFunctionReturn(0);
5747   case MAT_SUBSET_OFF_PROC_ENTRIES:
5748     mat->assembly_subset = flg;
5749     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5750 #if !defined(PETSC_HAVE_MPIUNI)
5751       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5752 #endif
5753       mat->stash.first_assembly_done = PETSC_FALSE;
5754     }
5755     PetscFunctionReturn(0);
5756   case MAT_NO_OFF_PROC_ZERO_ROWS: mat->nooffproczerorows = flg; PetscFunctionReturn(0);
5757   case MAT_SPD:
5758     if (flg) {
5759       mat->spd                    = PETSC_BOOL3_TRUE;
5760       mat->symmetric              = PETSC_BOOL3_TRUE;
5761       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5762     } else {
5763       mat->spd = PETSC_BOOL3_FALSE;
5764     }
5765     break;
5766   case MAT_SYMMETRIC:
5767     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5768     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5769 #if !defined(PETSC_USE_COMPLEX)
5770     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5771 #endif
5772     break;
5773   case MAT_HERMITIAN:
5774     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5775     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5776 #if !defined(PETSC_USE_COMPLEX)
5777     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5778 #endif
5779     break;
5780   case MAT_STRUCTURALLY_SYMMETRIC: mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE; break;
5781   case MAT_SYMMETRY_ETERNAL:
5782     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");
5783     mat->symmetry_eternal = flg;
5784     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5785     break;
5786   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5787     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");
5788     mat->structural_symmetry_eternal = flg;
5789     break;
5790   case MAT_SPD_ETERNAL:
5791     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");
5792     mat->spd_eternal = flg;
5793     if (flg) {
5794       mat->structural_symmetry_eternal = PETSC_TRUE;
5795       mat->symmetry_eternal            = PETSC_TRUE;
5796     }
5797     break;
5798   case MAT_STRUCTURE_ONLY: mat->structure_only = flg; break;
5799   case MAT_SORTED_FULL: mat->sortedfull = flg; break;
5800   default: break;
5801   }
5802   PetscTryTypeMethod(mat, setoption, op, flg);
5803   PetscFunctionReturn(0);
5804 }
5805 
5806 /*@
5807    MatGetOption - Gets a parameter option that has been set for a matrix.
5808 
5809    Logically Collective on mat
5810 
5811    Input Parameters:
5812 +  mat - the matrix
5813 -  option - the option, this only responds to certain options, check the code for which ones
5814 
5815    Output Parameter:
5816 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5817 
5818     Notes:
5819     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5820 
5821     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`, or
5822     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5823 
5824    Level: intermediate
5825 
5826 .seealso: `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`,  `MatIsStructurallySymmetric()`,
5827     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`,  `MatIsStructurallySymmetricKnown()`
5828 @*/
5829 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg) {
5830   PetscFunctionBegin;
5831   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5832   PetscValidType(mat, 1);
5833 
5834   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);
5835   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()");
5836 
5837   switch (op) {
5838   case MAT_NO_OFF_PROC_ENTRIES: *flg = mat->nooffprocentries; break;
5839   case MAT_NO_OFF_PROC_ZERO_ROWS: *flg = mat->nooffproczerorows; break;
5840   case MAT_SYMMETRIC: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()"); break;
5841   case MAT_HERMITIAN: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()"); break;
5842   case MAT_STRUCTURALLY_SYMMETRIC: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()"); break;
5843   case MAT_SPD: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()"); break;
5844   case MAT_SYMMETRY_ETERNAL: *flg = mat->symmetry_eternal; break;
5845   case MAT_STRUCTURAL_SYMMETRY_ETERNAL: *flg = mat->symmetry_eternal; break;
5846   default: break;
5847   }
5848   PetscFunctionReturn(0);
5849 }
5850 
5851 /*@
5852    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
5853    this routine retains the old nonzero structure.
5854 
5855    Logically Collective on mat
5856 
5857    Input Parameters:
5858 .  mat - the matrix
5859 
5860    Level: intermediate
5861 
5862    Note:
5863     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.
5864    See the Performance chapter of the users manual for information on preallocating matrices.
5865 
5866 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
5867 @*/
5868 PetscErrorCode MatZeroEntries(Mat mat) {
5869   PetscFunctionBegin;
5870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5871   PetscValidType(mat, 1);
5872   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5873   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");
5874   MatCheckPreallocated(mat, 1);
5875 
5876   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
5877   PetscUseTypeMethod(mat, zeroentries);
5878   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
5879   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5880   PetscFunctionReturn(0);
5881 }
5882 
5883 /*@
5884    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
5885    of a set of rows and columns of a matrix.
5886 
5887    Collective on mat
5888 
5889    Input Parameters:
5890 +  mat - the matrix
5891 .  numRows - the number of rows to remove
5892 .  rows - the global row indices
5893 .  diag - value put in the diagonal of the eliminated rows
5894 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5895 -  b - optional vector of right hand side, that will be adjusted by provided solution
5896 
5897    Notes:
5898    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5899 
5900    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5901    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
5902 
5903    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5904    Krylov method to take advantage of the known solution on the zeroed rows.
5905 
5906    For the parallel case, all processes that share the matrix (i.e.,
5907    those in the communicator used for matrix creation) MUST call this
5908    routine, regardless of whether any rows being zeroed are owned by
5909    them.
5910 
5911    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
5912 
5913    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
5914    list only rows local to itself).
5915 
5916    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
5917 
5918    Level: intermediate
5919 
5920 .seealso: `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5921           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
5922 @*/
5923 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
5924   PetscFunctionBegin;
5925   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5926   PetscValidType(mat, 1);
5927   if (numRows) PetscValidIntPointer(rows, 3);
5928   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5929   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5930   MatCheckPreallocated(mat, 1);
5931 
5932   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
5933   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5934   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5935   PetscFunctionReturn(0);
5936 }
5937 
5938 /*@
5939    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
5940    of a set of rows and columns of a matrix.
5941 
5942    Collective on mat
5943 
5944    Input Parameters:
5945 +  mat - the matrix
5946 .  is - the rows to zero
5947 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
5948 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
5949 -  b - optional vector of right hand side, that will be adjusted by provided solution
5950 
5951    Note:
5952    See `MatZeroRowsColumns()` for details on how this routine operates.
5953 
5954    Level: intermediate
5955 
5956 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
5957           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
5958 @*/
5959 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
5960   PetscInt        numRows;
5961   const PetscInt *rows;
5962 
5963   PetscFunctionBegin;
5964   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5965   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
5966   PetscValidType(mat, 1);
5967   PetscValidType(is, 2);
5968   PetscCall(ISGetLocalSize(is, &numRows));
5969   PetscCall(ISGetIndices(is, &rows));
5970   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
5971   PetscCall(ISRestoreIndices(is, &rows));
5972   PetscFunctionReturn(0);
5973 }
5974 
5975 /*@
5976    MatZeroRows - Zeros all entries (except possibly the main diagonal)
5977    of a set of rows of a matrix.
5978 
5979    Collective on mat
5980 
5981    Input Parameters:
5982 +  mat - the matrix
5983 .  numRows - the number of rows to remove
5984 .  rows - the global row indices
5985 .  diag - value put in the diagonal of the eliminated rows
5986 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
5987 -  b - optional vector of right hand side, that will be adjusted by provided solution
5988 
5989    Notes:
5990    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
5991 
5992    For each zeroed row, the value of the corresponding b is set to diag times the value of the corresponding x.
5993 
5994    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
5995    Krylov method to take advantage of the known solution on the zeroed rows.
5996 
5997    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)
5998    from the matrix.
5999 
6000    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6001    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
6002    formats this does not alter the nonzero structure.
6003 
6004    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6005    of the matrix is not changed the values are
6006    merely zeroed.
6007 
6008    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6009    formats can optionally remove the main diagonal entry from the
6010    nonzero structure as well, by passing 0.0 as the final argument).
6011 
6012    For the parallel case, all processes that share the matrix (i.e.,
6013    those in the communicator used for matrix creation) MUST call this
6014    routine, regardless of whether any rows being zeroed are owned by
6015    them.
6016 
6017    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6018    list only rows local to itself).
6019 
6020    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6021    owns that are to be zeroed. This saves a global synchronization in the implementation.
6022 
6023    Level: intermediate
6024 
6025 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6026           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6027 @*/
6028 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6029   PetscFunctionBegin;
6030   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6031   PetscValidType(mat, 1);
6032   if (numRows) PetscValidIntPointer(rows, 3);
6033   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6034   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6035   MatCheckPreallocated(mat, 1);
6036 
6037   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6038   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6039   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6040   PetscFunctionReturn(0);
6041 }
6042 
6043 /*@
6044    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6045    of a set of rows of a matrix.
6046 
6047    Collective on Mat
6048 
6049    Input Parameters:
6050 +  mat - the matrix
6051 .  is - index set of rows to remove (if NULL then no row is removed)
6052 .  diag - value put in all diagonals of eliminated rows
6053 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6054 -  b - optional vector of right hand side, that will be adjusted by provided solution
6055 
6056    Note:
6057    See `MatZeroRows()` for details on how this routine operates.
6058 
6059    Level: intermediate
6060 
6061 .seealso: `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6062           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6063 @*/
6064 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6065   PetscInt        numRows = 0;
6066   const PetscInt *rows    = NULL;
6067 
6068   PetscFunctionBegin;
6069   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6070   PetscValidType(mat, 1);
6071   if (is) {
6072     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6073     PetscCall(ISGetLocalSize(is, &numRows));
6074     PetscCall(ISGetIndices(is, &rows));
6075   }
6076   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6077   if (is) PetscCall(ISRestoreIndices(is, &rows));
6078   PetscFunctionReturn(0);
6079 }
6080 
6081 /*@
6082    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6083    of a set of rows of a matrix. These rows must be local to the process.
6084 
6085    Collective on mat
6086 
6087    Input Parameters:
6088 +  mat - the matrix
6089 .  numRows - the number of rows to remove
6090 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6091 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6092 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6093 -  b - optional vector of right hand side, that will be adjusted by provided solution
6094 
6095    Notes:
6096    See `MatZeroRows()` for details on how this routine operates.
6097 
6098    The grid coordinates are across the entire grid, not just the local portion
6099 
6100    In Fortran idxm and idxn should be declared as
6101 $     MatStencil idxm(4,m)
6102    and the values inserted using
6103 $    idxm(MatStencil_i,1) = i
6104 $    idxm(MatStencil_j,1) = j
6105 $    idxm(MatStencil_k,1) = k
6106 $    idxm(MatStencil_c,1) = c
6107    etc
6108 
6109    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6110    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6111    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6112    `DM_BOUNDARY_PERIODIC` boundary type.
6113 
6114    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
6115    a single value per point) you can skip filling those indices.
6116 
6117    Level: intermediate
6118 
6119 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6120           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6121 @*/
6122 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) {
6123   PetscInt  dim    = mat->stencil.dim;
6124   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6125   PetscInt *dims   = mat->stencil.dims + 1;
6126   PetscInt *starts = mat->stencil.starts;
6127   PetscInt *dxm    = (PetscInt *)rows;
6128   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6129 
6130   PetscFunctionBegin;
6131   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6132   PetscValidType(mat, 1);
6133   if (numRows) PetscValidPointer(rows, 3);
6134 
6135   PetscCall(PetscMalloc1(numRows, &jdxm));
6136   for (i = 0; i < numRows; ++i) {
6137     /* Skip unused dimensions (they are ordered k, j, i, c) */
6138     for (j = 0; j < 3 - sdim; ++j) dxm++;
6139     /* Local index in X dir */
6140     tmp = *dxm++ - starts[0];
6141     /* Loop over remaining dimensions */
6142     for (j = 0; j < dim - 1; ++j) {
6143       /* If nonlocal, set index to be negative */
6144       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6145       /* Update local index */
6146       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6147     }
6148     /* Skip component slot if necessary */
6149     if (mat->stencil.noc) dxm++;
6150     /* Local row number */
6151     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6152   }
6153   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6154   PetscCall(PetscFree(jdxm));
6155   PetscFunctionReturn(0);
6156 }
6157 
6158 /*@
6159    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6160    of a set of rows and columns of a matrix.
6161 
6162    Collective on mat
6163 
6164    Input Parameters:
6165 +  mat - the matrix
6166 .  numRows - the number of rows/columns to remove
6167 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6168 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6169 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6170 -  b - optional vector of right hand side, that will be adjusted by provided solution
6171 
6172    Notes:
6173    See `MatZeroRowsColumns()` for details on how this routine operates.
6174 
6175    The grid coordinates are across the entire grid, not just the local portion
6176 
6177    In Fortran idxm and idxn should be declared as
6178 $     MatStencil idxm(4,m)
6179    and the values inserted using
6180 $    idxm(MatStencil_i,1) = i
6181 $    idxm(MatStencil_j,1) = j
6182 $    idxm(MatStencil_k,1) = k
6183 $    idxm(MatStencil_c,1) = c
6184    etc
6185 
6186    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6187    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6188    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6189    `DM_BOUNDARY_PERIODIC` boundary type.
6190 
6191    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
6192    a single value per point) you can skip filling those indices.
6193 
6194    Level: intermediate
6195 
6196 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6197           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6198 @*/
6199 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b) {
6200   PetscInt  dim    = mat->stencil.dim;
6201   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6202   PetscInt *dims   = mat->stencil.dims + 1;
6203   PetscInt *starts = mat->stencil.starts;
6204   PetscInt *dxm    = (PetscInt *)rows;
6205   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6206 
6207   PetscFunctionBegin;
6208   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6209   PetscValidType(mat, 1);
6210   if (numRows) PetscValidPointer(rows, 3);
6211 
6212   PetscCall(PetscMalloc1(numRows, &jdxm));
6213   for (i = 0; i < numRows; ++i) {
6214     /* Skip unused dimensions (they are ordered k, j, i, c) */
6215     for (j = 0; j < 3 - sdim; ++j) dxm++;
6216     /* Local index in X dir */
6217     tmp = *dxm++ - starts[0];
6218     /* Loop over remaining dimensions */
6219     for (j = 0; j < dim - 1; ++j) {
6220       /* If nonlocal, set index to be negative */
6221       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6222       /* Update local index */
6223       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6224     }
6225     /* Skip component slot if necessary */
6226     if (mat->stencil.noc) dxm++;
6227     /* Local row number */
6228     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6229   }
6230   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6231   PetscCall(PetscFree(jdxm));
6232   PetscFunctionReturn(0);
6233 }
6234 
6235 /*@C
6236    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6237    of a set of rows of a matrix; using local numbering of rows.
6238 
6239    Collective on mat
6240 
6241    Input Parameters:
6242 +  mat - the matrix
6243 .  numRows - the number of rows to remove
6244 .  rows - the local row indices
6245 .  diag - value put in all diagonals of eliminated rows
6246 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6247 -  b - optional vector of right hand side, that will be adjusted by provided solution
6248 
6249    Notes:
6250    Before calling `MatZeroRowsLocal()`, the user must first set the
6251    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6252 
6253    See `MatZeroRows()` for details on how this routine operates.
6254 
6255    Level: intermediate
6256 
6257 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6258           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6259 @*/
6260 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6261   PetscFunctionBegin;
6262   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6263   PetscValidType(mat, 1);
6264   if (numRows) PetscValidIntPointer(rows, 3);
6265   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6266   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6267   MatCheckPreallocated(mat, 1);
6268 
6269   if (mat->ops->zerorowslocal) {
6270     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6271   } else {
6272     IS              is, newis;
6273     const PetscInt *newRows;
6274 
6275     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6276     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6277     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6278     PetscCall(ISGetIndices(newis, &newRows));
6279     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6280     PetscCall(ISRestoreIndices(newis, &newRows));
6281     PetscCall(ISDestroy(&newis));
6282     PetscCall(ISDestroy(&is));
6283   }
6284   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6285   PetscFunctionReturn(0);
6286 }
6287 
6288 /*@
6289    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6290    of a set of rows of a matrix; using local numbering of rows.
6291 
6292    Collective on mat
6293 
6294    Input Parameters:
6295 +  mat - the matrix
6296 .  is - index set of rows to remove
6297 .  diag - value put in all diagonals of eliminated rows
6298 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6299 -  b - optional vector of right hand side, that will be adjusted by provided solution
6300 
6301    Notes:
6302    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6303    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6304 
6305    See `MatZeroRows()` for details on how this routine operates.
6306 
6307    Level: intermediate
6308 
6309 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6310           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6311 @*/
6312 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6313   PetscInt        numRows;
6314   const PetscInt *rows;
6315 
6316   PetscFunctionBegin;
6317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6318   PetscValidType(mat, 1);
6319   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6320   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6321   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6322   MatCheckPreallocated(mat, 1);
6323 
6324   PetscCall(ISGetLocalSize(is, &numRows));
6325   PetscCall(ISGetIndices(is, &rows));
6326   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6327   PetscCall(ISRestoreIndices(is, &rows));
6328   PetscFunctionReturn(0);
6329 }
6330 
6331 /*@
6332    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6333    of a set of rows and columns of a matrix; using local numbering of rows.
6334 
6335    Collective on mat
6336 
6337    Input Parameters:
6338 +  mat - the matrix
6339 .  numRows - the number of rows to remove
6340 .  rows - the global row indices
6341 .  diag - value put in all diagonals of eliminated rows
6342 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6343 -  b - optional vector of right hand side, that will be adjusted by provided solution
6344 
6345    Notes:
6346    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6347    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6348 
6349    See `MatZeroRowsColumns()` for details on how this routine operates.
6350 
6351    Level: intermediate
6352 
6353 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6354           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6355 @*/
6356 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b) {
6357   IS              is, newis;
6358   const PetscInt *newRows;
6359 
6360   PetscFunctionBegin;
6361   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6362   PetscValidType(mat, 1);
6363   if (numRows) PetscValidIntPointer(rows, 3);
6364   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6365   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6366   MatCheckPreallocated(mat, 1);
6367 
6368   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6369   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6370   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6371   PetscCall(ISGetIndices(newis, &newRows));
6372   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6373   PetscCall(ISRestoreIndices(newis, &newRows));
6374   PetscCall(ISDestroy(&newis));
6375   PetscCall(ISDestroy(&is));
6376   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6377   PetscFunctionReturn(0);
6378 }
6379 
6380 /*@
6381    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6382    of a set of rows and columns of a matrix; using local numbering of rows.
6383 
6384    Collective on Mat
6385 
6386    Input Parameters:
6387 +  mat - the matrix
6388 .  is - index set of rows to remove
6389 .  diag - value put in all diagonals of eliminated rows
6390 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6391 -  b - optional vector of right hand side, that will be adjusted by provided solution
6392 
6393    Notes:
6394    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6395    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6396 
6397    See `MatZeroRowsColumns()` for details on how this routine operates.
6398 
6399    Level: intermediate
6400 
6401 .seealso: `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6402           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6403 @*/
6404 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b) {
6405   PetscInt        numRows;
6406   const PetscInt *rows;
6407 
6408   PetscFunctionBegin;
6409   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6410   PetscValidType(mat, 1);
6411   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6412   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6413   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6414   MatCheckPreallocated(mat, 1);
6415 
6416   PetscCall(ISGetLocalSize(is, &numRows));
6417   PetscCall(ISGetIndices(is, &rows));
6418   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6419   PetscCall(ISRestoreIndices(is, &rows));
6420   PetscFunctionReturn(0);
6421 }
6422 
6423 /*@C
6424    MatGetSize - Returns the numbers of rows and columns in a matrix.
6425 
6426    Not Collective
6427 
6428    Input Parameter:
6429 .  mat - the matrix
6430 
6431    Output Parameters:
6432 +  m - the number of global rows
6433 -  n - the number of global columns
6434 
6435    Note: both output parameters can be NULL on input.
6436 
6437    Level: beginner
6438 
6439 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6440 @*/
6441 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n) {
6442   PetscFunctionBegin;
6443   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6444   if (m) *m = mat->rmap->N;
6445   if (n) *n = mat->cmap->N;
6446   PetscFunctionReturn(0);
6447 }
6448 
6449 /*@C
6450    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6451    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6452 
6453    Not Collective
6454 
6455    Input Parameter:
6456 .  mat - the matrix
6457 
6458    Output Parameters:
6459 +  m - the number of local rows, use `NULL` to not obtain this value
6460 -  n - the number of local columns, use `NULL` to not obtain this value
6461 
6462    Level: beginner
6463 
6464 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6465 @*/
6466 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n) {
6467   PetscFunctionBegin;
6468   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6469   if (m) PetscValidIntPointer(m, 2);
6470   if (n) PetscValidIntPointer(n, 3);
6471   if (m) *m = mat->rmap->n;
6472   if (n) *n = mat->cmap->n;
6473   PetscFunctionReturn(0);
6474 }
6475 
6476 /*@C
6477    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6478    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6479 
6480    Not Collective, unless matrix has not been allocated, then collective on mat
6481 
6482    Input Parameter:
6483 .  mat - the matrix
6484 
6485    Output Parameters:
6486 +  m - the global index of the first local column, use `NULL` to not obtain this value
6487 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6488 
6489    Level: developer
6490 
6491 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6492 @*/
6493 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n) {
6494   PetscFunctionBegin;
6495   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6496   PetscValidType(mat, 1);
6497   if (m) PetscValidIntPointer(m, 2);
6498   if (n) PetscValidIntPointer(n, 3);
6499   MatCheckPreallocated(mat, 1);
6500   if (m) *m = mat->cmap->rstart;
6501   if (n) *n = mat->cmap->rend;
6502   PetscFunctionReturn(0);
6503 }
6504 
6505 /*@C
6506    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6507    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
6508    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6509 
6510    Not Collective
6511 
6512    Input Parameter:
6513 .  mat - the matrix
6514 
6515    Output Parameters:
6516 +  m - the global index of the first local row, use `NULL` to not obtain this value
6517 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6518 
6519    Note:
6520   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6521   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6522   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6523 
6524    Level: beginner
6525 
6526 .seealso: `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6527           `PetscLayout`
6528 @*/
6529 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n) {
6530   PetscFunctionBegin;
6531   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6532   PetscValidType(mat, 1);
6533   if (m) PetscValidIntPointer(m, 2);
6534   if (n) PetscValidIntPointer(n, 3);
6535   MatCheckPreallocated(mat, 1);
6536   if (m) *m = mat->rmap->rstart;
6537   if (n) *n = mat->rmap->rend;
6538   PetscFunctionReturn(0);
6539 }
6540 
6541 /*@C
6542    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6543    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
6544    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6545 
6546    Not Collective, unless matrix has not been allocated, then collective on mat
6547 
6548    Input Parameters:
6549 .  mat - the matrix
6550 
6551    Output Parameters:
6552 .  ranges - start of each processors portion plus one more than the total length at the end
6553 
6554    Level: beginner
6555 
6556 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6557 @*/
6558 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges) {
6559   PetscFunctionBegin;
6560   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6561   PetscValidType(mat, 1);
6562   MatCheckPreallocated(mat, 1);
6563   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6564   PetscFunctionReturn(0);
6565 }
6566 
6567 /*@C
6568    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6569    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6570 
6571    Not Collective, unless matrix has not been allocated, then collective on Mat
6572 
6573    Input Parameters:
6574 .  mat - the matrix
6575 
6576    Output Parameters:
6577 .  ranges - start of each processors portion plus one more then the total length at the end
6578 
6579    Level: beginner
6580 
6581 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6582 @*/
6583 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges) {
6584   PetscFunctionBegin;
6585   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6586   PetscValidType(mat, 1);
6587   MatCheckPreallocated(mat, 1);
6588   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6589   PetscFunctionReturn(0);
6590 }
6591 
6592 /*@C
6593    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6594    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6595    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6596 
6597    Not Collective
6598 
6599    Input Parameter:
6600 .  A - matrix
6601 
6602    Output Parameters:
6603 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6604 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6605 
6606    Level: intermediate
6607 
6608 .seealso: `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6609 @*/
6610 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols) {
6611   PetscErrorCode (*f)(Mat, IS *, IS *);
6612 
6613   PetscFunctionBegin;
6614   MatCheckPreallocated(A, 1);
6615   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6616   if (f) {
6617     PetscCall((*f)(A, rows, cols));
6618   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6619     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6620     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6621   }
6622   PetscFunctionReturn(0);
6623 }
6624 
6625 /*@C
6626    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6627    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6628    to complete the factorization.
6629 
6630    Collective on fact
6631 
6632    Input Parameters:
6633 +  fact - the factorized matrix obtained with `MatGetFactor()`
6634 .  mat - the matrix
6635 .  row - row permutation
6636 .  column - column permutation
6637 -  info - structure containing
6638 $      levels - number of levels of fill.
6639 $      expected fill - as ratio of original fill.
6640 $      1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6641                 missing diagonal entries)
6642 
6643    Output Parameters:
6644 .  fact - new matrix that has been symbolically factored
6645 
6646    Level: developer
6647 
6648    Notes:
6649    See [Matrix Factorization](sec_matfactor) for additional information.
6650 
6651    Most users should employ the `KSP` interface for linear solvers
6652    instead of working directly with matrix algebra routines such as this.
6653    See, e.g., `KSPCreate()`.
6654 
6655    Uses the definition of level of fill as in Y. Saad, 2003
6656 
6657    Developer Note:
6658    The Fortran interface is not autogenerated as the f90
6659    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6660 
6661    References:
6662 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6663 
6664 .seealso: [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6665           `MatGetOrdering()`, `MatFactorInfo`
6666 @*/
6667 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info) {
6668   PetscFunctionBegin;
6669   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6670   PetscValidType(mat, 2);
6671   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6672   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6673   PetscValidPointer(info, 5);
6674   PetscValidPointer(fact, 1);
6675   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6676   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6677   if (!fact->ops->ilufactorsymbolic) {
6678     MatSolverType stype;
6679     PetscCall(MatFactorGetSolverType(fact, &stype));
6680     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6681   }
6682   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6683   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6684   MatCheckPreallocated(mat, 2);
6685 
6686   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6687   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6688   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6689   PetscFunctionReturn(0);
6690 }
6691 
6692 /*@C
6693    MatICCFactorSymbolic - Performs symbolic incomplete
6694    Cholesky factorization for a symmetric matrix.  Use
6695    `MatCholeskyFactorNumeric()` to complete the factorization.
6696 
6697    Collective on fact
6698 
6699    Input Parameters:
6700 +  fact - the factorized matrix obtained with `MatGetFactor()`
6701 .  mat - the matrix to be factored
6702 .  perm - row and column permutation
6703 -  info - structure containing
6704 $      levels - number of levels of fill.
6705 $      expected fill - as ratio of original fill.
6706 
6707    Output Parameter:
6708 .  fact - the factored matrix
6709 
6710    Level: developer
6711 
6712    Notes:
6713    Most users should employ the `KSP` interface for linear solvers
6714    instead of working directly with matrix algebra routines such as this.
6715    See, e.g., `KSPCreate()`.
6716 
6717    This uses the definition of level of fill as in Y. Saad, 2003
6718 
6719    Developer Note:
6720    The Fortran interface is not autogenerated as the f90
6721    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6722 
6723    References:
6724 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6725 
6726 .seealso: `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6727 @*/
6728 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info) {
6729   PetscFunctionBegin;
6730   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6731   PetscValidType(mat, 2);
6732   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6733   PetscValidPointer(info, 4);
6734   PetscValidPointer(fact, 1);
6735   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6736   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6737   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6738   if (!(fact)->ops->iccfactorsymbolic) {
6739     MatSolverType stype;
6740     PetscCall(MatFactorGetSolverType(fact, &stype));
6741     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6742   }
6743   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6744   MatCheckPreallocated(mat, 2);
6745 
6746   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6747   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6748   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6749   PetscFunctionReturn(0);
6750 }
6751 
6752 /*@C
6753    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6754    points to an array of valid matrices, they may be reused to store the new
6755    submatrices.
6756 
6757    Collective on mat
6758 
6759    Input Parameters:
6760 +  mat - the matrix
6761 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6762 .  irow, icol - index sets of rows and columns to extract
6763 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6764 
6765    Output Parameter:
6766 .  submat - the array of submatrices
6767 
6768    Notes:
6769    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6770    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6771    to extract a parallel submatrix.
6772 
6773    Some matrix types place restrictions on the row and column
6774    indices, such as that they be sorted or that they be equal to each other.
6775 
6776    The index sets may not have duplicate entries.
6777 
6778    When extracting submatrices from a parallel matrix, each processor can
6779    form a different submatrix by setting the rows and columns of its
6780    individual index sets according to the local submatrix desired.
6781 
6782    When finished using the submatrices, the user should destroy
6783    them with `MatDestroySubMatrices()`.
6784 
6785    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6786    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6787 
6788    This routine creates the matrices in submat; you should NOT create them before
6789    calling it. It also allocates the array of matrix pointers submat.
6790 
6791    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6792    request one row/column in a block, they must request all rows/columns that are in
6793    that block. For example, if the block size is 2 you cannot request just row 0 and
6794    column 0.
6795 
6796    Fortran Note:
6797    The Fortran interface is slightly different from that given below; it
6798    requires one to pass in  as submat a `Mat` (integer) array of size at least n+1.
6799 
6800    Level: advanced
6801 
6802 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6803 @*/
6804 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) {
6805   PetscInt  i;
6806   PetscBool eq;
6807 
6808   PetscFunctionBegin;
6809   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6810   PetscValidType(mat, 1);
6811   if (n) {
6812     PetscValidPointer(irow, 3);
6813     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
6814     PetscValidPointer(icol, 4);
6815     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
6816   }
6817   PetscValidPointer(submat, 6);
6818   if (n && scall == MAT_REUSE_MATRIX) {
6819     PetscValidPointer(*submat, 6);
6820     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
6821   }
6822   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6823   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6824   MatCheckPreallocated(mat, 1);
6825   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
6826   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
6827   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
6828   for (i = 0; i < n; i++) {
6829     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
6830     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
6831     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
6832 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
6833     if (mat->boundtocpu && mat->bindingpropagates) {
6834       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
6835       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
6836     }
6837 #endif
6838   }
6839   PetscFunctionReturn(0);
6840 }
6841 
6842 /*@C
6843    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
6844 
6845    Collective on mat
6846 
6847    Input Parameters:
6848 +  mat - the matrix
6849 .  n   - the number of submatrixes to be extracted
6850 .  irow, icol - index sets of rows and columns to extract
6851 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6852 
6853    Output Parameter:
6854 .  submat - the array of submatrices
6855 
6856    Level: advanced
6857 
6858    Note:
6859    This is used by `PCGASM`
6860 
6861 .seealso: `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6862 @*/
6863 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[]) {
6864   PetscInt  i;
6865   PetscBool eq;
6866 
6867   PetscFunctionBegin;
6868   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6869   PetscValidType(mat, 1);
6870   if (n) {
6871     PetscValidPointer(irow, 3);
6872     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
6873     PetscValidPointer(icol, 4);
6874     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
6875   }
6876   PetscValidPointer(submat, 6);
6877   if (n && scall == MAT_REUSE_MATRIX) {
6878     PetscValidPointer(*submat, 6);
6879     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
6880   }
6881   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6882   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6883   MatCheckPreallocated(mat, 1);
6884 
6885   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
6886   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
6887   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
6888   for (i = 0; i < n; i++) {
6889     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
6890     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
6891   }
6892   PetscFunctionReturn(0);
6893 }
6894 
6895 /*@C
6896    MatDestroyMatrices - Destroys an array of matrices.
6897 
6898    Collective on mat
6899 
6900    Input Parameters:
6901 +  n - the number of local matrices
6902 -  mat - the matrices (note that this is a pointer to the array of matrices)
6903 
6904    Level: advanced
6905 
6906     Note:
6907     Frees not only the matrices, but also the array that contains the matrices
6908            In Fortran will not free the array.
6909 
6910 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
6911 @*/
6912 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[]) {
6913   PetscInt i;
6914 
6915   PetscFunctionBegin;
6916   if (!*mat) PetscFunctionReturn(0);
6917   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
6918   PetscValidPointer(mat, 2);
6919 
6920   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
6921 
6922   /* memory is allocated even if n = 0 */
6923   PetscCall(PetscFree(*mat));
6924   PetscFunctionReturn(0);
6925 }
6926 
6927 /*@C
6928    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
6929 
6930    Collective on mat
6931 
6932    Input Parameters:
6933 +  n - the number of local matrices
6934 -  mat - the matrices (note that this is a pointer to the array of matrices, just to match the calling
6935                        sequence of MatCreateSubMatrices())
6936 
6937    Level: advanced
6938 
6939     Note:
6940     Frees not only the matrices, but also the array that contains the matrices
6941            In Fortran will not free the array.
6942 
6943 .seealso: `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6944 @*/
6945 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[]) {
6946   Mat mat0;
6947 
6948   PetscFunctionBegin;
6949   if (!*mat) PetscFunctionReturn(0);
6950   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
6951   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
6952   PetscValidPointer(mat, 2);
6953 
6954   mat0 = (*mat)[0];
6955   if (mat0 && mat0->ops->destroysubmatrices) {
6956     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
6957   } else {
6958     PetscCall(MatDestroyMatrices(n, mat));
6959   }
6960   PetscFunctionReturn(0);
6961 }
6962 
6963 /*@C
6964    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
6965 
6966    Collective on mat
6967 
6968    Input Parameters:
6969 .  mat - the matrix
6970 
6971    Output Parameter:
6972 .  matstruct - the sequential matrix with the nonzero structure of mat
6973 
6974   Level: developer
6975 
6976 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
6977 @*/
6978 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct) {
6979   PetscFunctionBegin;
6980   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6981   PetscValidPointer(matstruct, 2);
6982 
6983   PetscValidType(mat, 1);
6984   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6985   MatCheckPreallocated(mat, 1);
6986 
6987   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
6988   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
6989   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
6990   PetscFunctionReturn(0);
6991 }
6992 
6993 /*@C
6994    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
6995 
6996    Collective on mat
6997 
6998    Input Parameters:
6999 .  mat - the matrix (note that this is a pointer to the array of matrices, just to match the calling
7000                        sequence of `MatGetSequentialNonzeroStructure()`)
7001 
7002    Level: advanced
7003 
7004     Note:
7005     Frees not only the matrices, but also the array that contains the matrices
7006 
7007 .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7008 @*/
7009 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat) {
7010   PetscFunctionBegin;
7011   PetscValidPointer(mat, 1);
7012   PetscCall(MatDestroy(mat));
7013   PetscFunctionReturn(0);
7014 }
7015 
7016 /*@
7017    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7018    replaces the index sets by larger ones that represent submatrices with
7019    additional overlap.
7020 
7021    Collective on mat
7022 
7023    Input Parameters:
7024 +  mat - the matrix
7025 .  n   - the number of index sets
7026 .  is  - the array of index sets (these index sets will changed during the call)
7027 -  ov  - the additional overlap requested
7028 
7029    Options Database:
7030 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7031 
7032    Level: developer
7033 
7034    Developer Note:
7035    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.
7036 
7037 .seealso: `Mat`, `PCASM`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7038 @*/
7039 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov) {
7040   PetscInt i, bs, cbs;
7041 
7042   PetscFunctionBegin;
7043   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7044   PetscValidType(mat, 1);
7045   PetscValidLogicalCollectiveInt(mat, n, 2);
7046   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7047   if (n) {
7048     PetscValidPointer(is, 3);
7049     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7050   }
7051   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7052   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7053   MatCheckPreallocated(mat, 1);
7054 
7055   if (!ov || !n) PetscFunctionReturn(0);
7056   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7057   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7058   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7059   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7060   if (bs == cbs) {
7061     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7062   }
7063   PetscFunctionReturn(0);
7064 }
7065 
7066 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7067 
7068 /*@
7069    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7070    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7071    additional overlap.
7072 
7073    Collective on mat
7074 
7075    Input Parameters:
7076 +  mat - the matrix
7077 .  n   - the number of index sets
7078 .  is  - the array of index sets (these index sets will changed during the call)
7079 -  ov  - the additional overlap requested
7080 
7081 `   Options Database:
7082 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7083 
7084    Level: developer
7085 
7086 .seealso: `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7087 @*/
7088 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov) {
7089   PetscInt i;
7090 
7091   PetscFunctionBegin;
7092   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7093   PetscValidType(mat, 1);
7094   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7095   if (n) {
7096     PetscValidPointer(is, 3);
7097     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7098   }
7099   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7100   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7101   MatCheckPreallocated(mat, 1);
7102   if (!ov) PetscFunctionReturn(0);
7103   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7104   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7105   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7106   PetscFunctionReturn(0);
7107 }
7108 
7109 /*@
7110    MatGetBlockSize - Returns the matrix block size.
7111 
7112    Not Collective
7113 
7114    Input Parameter:
7115 .  mat - the matrix
7116 
7117    Output Parameter:
7118 .  bs - block size
7119 
7120    Notes:
7121     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7122 
7123    If the block size has not been set yet this routine returns 1.
7124 
7125    Level: intermediate
7126 
7127 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7128 @*/
7129 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs) {
7130   PetscFunctionBegin;
7131   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7132   PetscValidIntPointer(bs, 2);
7133   *bs = PetscAbs(mat->rmap->bs);
7134   PetscFunctionReturn(0);
7135 }
7136 
7137 /*@
7138    MatGetBlockSizes - Returns the matrix block row and column sizes.
7139 
7140    Not Collective
7141 
7142    Input Parameter:
7143 .  mat - the matrix
7144 
7145    Output Parameters:
7146 +  rbs - row block size
7147 -  cbs - column block size
7148 
7149    Notes:
7150     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7151     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7152 
7153    If a block size has not been set yet this routine returns 1.
7154 
7155    Level: intermediate
7156 
7157 .seealso: `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7158 @*/
7159 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs) {
7160   PetscFunctionBegin;
7161   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7162   if (rbs) PetscValidIntPointer(rbs, 2);
7163   if (cbs) PetscValidIntPointer(cbs, 3);
7164   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7165   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7166   PetscFunctionReturn(0);
7167 }
7168 
7169 /*@
7170    MatSetBlockSize - Sets the matrix block size.
7171 
7172    Logically Collective on mat
7173 
7174    Input Parameters:
7175 +  mat - the matrix
7176 -  bs - block size
7177 
7178    Notes:
7179     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7180     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7181 
7182     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7183     is compatible with the matrix local sizes.
7184 
7185    Level: intermediate
7186 
7187 .seealso:  `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7188 @*/
7189 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs) {
7190   PetscFunctionBegin;
7191   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7192   PetscValidLogicalCollectiveInt(mat, bs, 2);
7193   PetscCall(MatSetBlockSizes(mat, bs, bs));
7194   PetscFunctionReturn(0);
7195 }
7196 
7197 typedef struct {
7198   PetscInt         n;
7199   IS              *is;
7200   Mat             *mat;
7201   PetscObjectState nonzerostate;
7202   Mat              C;
7203 } EnvelopeData;
7204 
7205 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata) {
7206   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7207   PetscCall(PetscFree(edata->is));
7208   PetscCall(PetscFree(edata));
7209   return 0;
7210 }
7211 
7212 /*
7213    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7214          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7215 
7216    Collective on mat
7217 
7218    Input Parameter:
7219 .  mat - the matrix
7220 
7221    Notes:
7222      There can be zeros within the blocks
7223 
7224      The blocks can overlap between processes, including laying on more than two processes
7225 
7226 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7227 */
7228 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat) {
7229   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7230   PetscInt          *diag, *odiag, sc;
7231   VecScatter         scatter;
7232   PetscScalar       *seqv;
7233   const PetscScalar *parv;
7234   const PetscInt    *ia, *ja;
7235   PetscBool          set, flag, done;
7236   Mat                AA = mat, A;
7237   MPI_Comm           comm;
7238   PetscMPIInt        rank, size, tag;
7239   MPI_Status         status;
7240   PetscContainer     container;
7241   EnvelopeData      *edata;
7242   Vec                seq, par;
7243   IS                 isglobal;
7244 
7245   PetscFunctionBegin;
7246   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7247   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7248   if (!set || !flag) {
7249     /* TOO: only needs nonzero structure of transpose */
7250     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7251     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7252   }
7253   PetscCall(MatAIJGetLocalMat(AA, &A));
7254   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7255   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7256 
7257   PetscCall(MatGetLocalSize(mat, &n, NULL));
7258   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7259   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7260   PetscCallMPI(MPI_Comm_size(comm, &size));
7261   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7262 
7263   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7264 
7265   if (rank > 0) {
7266     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7267     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7268   }
7269   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7270   for (i = 0; i < n; i++) {
7271     env = PetscMax(env, ja[ia[i + 1] - 1]);
7272     II  = rstart + i;
7273     if (env == II) {
7274       starts[lblocks]  = tbs;
7275       sizes[lblocks++] = 1 + II - tbs;
7276       tbs              = 1 + II;
7277     }
7278   }
7279   if (rank < size - 1) {
7280     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7281     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7282   }
7283 
7284   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7285   if (!set || !flag) PetscCall(MatDestroy(&AA));
7286   PetscCall(MatDestroy(&A));
7287 
7288   PetscCall(PetscNew(&edata));
7289   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7290   edata->n = lblocks;
7291   /* create IS needed for extracting blocks from the original matrix */
7292   PetscCall(PetscMalloc1(lblocks, &edata->is));
7293   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7294 
7295   /* Create the resulting inverse matrix structure with preallocation information */
7296   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7297   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7298   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7299   PetscCall(MatSetType(edata->C, MATAIJ));
7300 
7301   /* Communicate the start and end of each row, from each block to the correct rank */
7302   /* TODO: Use PetscSF instead of VecScatter */
7303   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7304   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7305   PetscCall(VecGetArrayWrite(seq, &seqv));
7306   for (PetscInt i = 0; i < lblocks; i++) {
7307     for (PetscInt j = 0; j < sizes[i]; j++) {
7308       seqv[cnt]     = starts[i];
7309       seqv[cnt + 1] = starts[i] + sizes[i];
7310       cnt += 2;
7311     }
7312   }
7313   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7314   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7315   sc -= cnt;
7316   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7317   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7318   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7319   PetscCall(ISDestroy(&isglobal));
7320   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7321   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7322   PetscCall(VecScatterDestroy(&scatter));
7323   PetscCall(VecDestroy(&seq));
7324   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7325   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7326   PetscCall(VecGetArrayRead(par, &parv));
7327   cnt = 0;
7328   PetscCall(MatGetSize(mat, NULL, &n));
7329   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7330     PetscInt start, end, d = 0, od = 0;
7331 
7332     start = (PetscInt)PetscRealPart(parv[cnt]);
7333     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7334     cnt += 2;
7335 
7336     if (start < cstart) {
7337       od += cstart - start + n - cend;
7338       d += cend - cstart;
7339     } else if (start < cend) {
7340       od += n - cend;
7341       d += cend - start;
7342     } else od += n - start;
7343     if (end <= cstart) {
7344       od -= cstart - end + n - cend;
7345       d -= cend - cstart;
7346     } else if (end < cend) {
7347       od -= n - cend;
7348       d -= cend - end;
7349     } else od -= n - end;
7350 
7351     odiag[i] = od;
7352     diag[i]  = d;
7353   }
7354   PetscCall(VecRestoreArrayRead(par, &parv));
7355   PetscCall(VecDestroy(&par));
7356   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7357   PetscCall(PetscFree2(diag, odiag));
7358   PetscCall(PetscFree2(sizes, starts));
7359 
7360   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7361   PetscCall(PetscContainerSetPointer(container, edata));
7362   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7363   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7364   PetscCall(PetscObjectDereference((PetscObject)container));
7365   PetscFunctionReturn(0);
7366 }
7367 
7368 /*@
7369   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7370 
7371   Collective on A
7372 
7373   Input Parameters:
7374 . A - the matrix
7375 
7376   Output Parameters:
7377 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7378 
7379   Note:
7380      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7381 
7382   Level: advanced
7383 
7384 .seealso: `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7385 @*/
7386 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C) {
7387   PetscContainer   container;
7388   EnvelopeData    *edata;
7389   PetscObjectState nonzerostate;
7390 
7391   PetscFunctionBegin;
7392   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7393   if (!container) {
7394     PetscCall(MatComputeVariableBlockEnvelope(A));
7395     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7396   }
7397   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7398   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7399   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7400   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7401 
7402   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7403   *C = edata->C;
7404 
7405   for (PetscInt i = 0; i < edata->n; i++) {
7406     Mat          D;
7407     PetscScalar *dvalues;
7408 
7409     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7410     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7411     PetscCall(MatSeqDenseInvert(D));
7412     PetscCall(MatDenseGetArray(D, &dvalues));
7413     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7414     PetscCall(MatDestroy(&D));
7415   }
7416   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7417   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7418   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7419   PetscFunctionReturn(0);
7420 }
7421 
7422 /*@
7423    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7424 
7425    Logically Collective on mat
7426 
7427    Input Parameters:
7428 +  mat - the matrix
7429 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7430 -  bsizes - the block sizes
7431 
7432    Notes:
7433     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7434 
7435     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.
7436 
7437    Level: intermediate
7438 
7439 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7440           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7441 @*/
7442 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes) {
7443   PetscInt i, ncnt = 0, nlocal;
7444 
7445   PetscFunctionBegin;
7446   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7447   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7448   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7449   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7450   PetscCheck(ncnt == nlocal, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Sum of local block sizes %" PetscInt_FMT " does not equal local size of matrix %" PetscInt_FMT, ncnt, nlocal);
7451   PetscCall(PetscFree(mat->bsizes));
7452   mat->nblocks = nblocks;
7453   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7454   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7455   PetscFunctionReturn(0);
7456 }
7457 
7458 /*@C
7459    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7460 
7461    Logically Collective on mat
7462 
7463    Input Parameter:
7464 .  mat - the matrix
7465 
7466    Output Parameters:
7467 +  nblocks - the number of blocks on this process
7468 -  bsizes - the block sizes
7469 
7470    Fortran Note:
7471    Currently not supported from Fortran
7472 
7473    Level: intermediate
7474 
7475 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7476 @*/
7477 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes) {
7478   PetscFunctionBegin;
7479   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7480   *nblocks = mat->nblocks;
7481   *bsizes  = mat->bsizes;
7482   PetscFunctionReturn(0);
7483 }
7484 
7485 /*@
7486    MatSetBlockSizes - Sets the matrix block row and column sizes.
7487 
7488    Logically Collective on mat
7489 
7490    Input Parameters:
7491 +  mat - the matrix
7492 .  rbs - row block size
7493 -  cbs - column block size
7494 
7495    Notes:
7496     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7497     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7498     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7499 
7500     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7501     are compatible with the matrix local sizes.
7502 
7503     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7504 
7505    Level: intermediate
7506 
7507 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7508 @*/
7509 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs) {
7510   PetscFunctionBegin;
7511   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7512   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7513   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7514   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7515   if (mat->rmap->refcnt) {
7516     ISLocalToGlobalMapping l2g  = NULL;
7517     PetscLayout            nmap = NULL;
7518 
7519     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7520     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7521     PetscCall(PetscLayoutDestroy(&mat->rmap));
7522     mat->rmap          = nmap;
7523     mat->rmap->mapping = l2g;
7524   }
7525   if (mat->cmap->refcnt) {
7526     ISLocalToGlobalMapping l2g  = NULL;
7527     PetscLayout            nmap = NULL;
7528 
7529     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7530     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7531     PetscCall(PetscLayoutDestroy(&mat->cmap));
7532     mat->cmap          = nmap;
7533     mat->cmap->mapping = l2g;
7534   }
7535   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7536   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7537   PetscFunctionReturn(0);
7538 }
7539 
7540 /*@
7541    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7542 
7543    Logically Collective on mat
7544 
7545    Input Parameters:
7546 +  mat - the matrix
7547 .  fromRow - matrix from which to copy row block size
7548 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7549 
7550    Level: developer
7551 
7552 .seealso: `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7553 @*/
7554 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol) {
7555   PetscFunctionBegin;
7556   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7557   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7558   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7559   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7560   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7561   PetscFunctionReturn(0);
7562 }
7563 
7564 /*@
7565    MatResidual - Default routine to calculate the residual r = b - Ax
7566 
7567    Collective on mat
7568 
7569    Input Parameters:
7570 +  mat - the matrix
7571 .  b   - the right-hand-side
7572 -  x   - the approximate solution
7573 
7574    Output Parameter:
7575 .  r - location to store the residual
7576 
7577    Level: developer
7578 
7579 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7580 @*/
7581 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r) {
7582   PetscFunctionBegin;
7583   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7584   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7585   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7586   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7587   PetscValidType(mat, 1);
7588   MatCheckPreallocated(mat, 1);
7589   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7590   if (!mat->ops->residual) {
7591     PetscCall(MatMult(mat, x, r));
7592     PetscCall(VecAYPX(r, -1.0, b));
7593   } else {
7594     PetscUseTypeMethod(mat, residual, b, x, r);
7595   }
7596   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7597   PetscFunctionReturn(0);
7598 }
7599 
7600 /*@C
7601     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7602 
7603    Collective on mat
7604 
7605     Input Parameters:
7606 +   mat - the matrix
7607 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7608 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7609 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7610                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7611                  always used.
7612 
7613     Output Parameters:
7614 +   n - number of local rows in the (possibly compressed) matrix, use NULL if not needed
7615 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix, use NULL if not needed
7616 .   ja - the column indices, use NULL if not needed
7617 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7618            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7619 
7620     Level: developer
7621 
7622     Notes:
7623     You CANNOT change any of the ia[] or ja[] values.
7624 
7625     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7626 
7627     Fortran Notes:
7628     In Fortran use
7629 $
7630 $      PetscInt ia(1), ja(1)
7631 $      PetscOffset iia, jja
7632 $      call MatGetRowIJ(mat,shift,symmetric,inodecompressed,n,ia,iia,ja,jja,done,ierr)
7633 $      ! Access the ith and jth entries via ia(iia + i) and ja(jja + j)
7634 
7635      or
7636 $
7637 $    PetscInt, pointer :: ia(:),ja(:)
7638 $    call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7639 $    ! Access the ith and jth entries via ia(i) and ja(j)
7640 
7641 .seealso: `Mat`, `MATAIJ`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7642 @*/
7643 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7644   PetscFunctionBegin;
7645   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7646   PetscValidType(mat, 1);
7647   if (n) PetscValidIntPointer(n, 5);
7648   if (ia) PetscValidPointer(ia, 6);
7649   if (ja) PetscValidPointer(ja, 7);
7650   if (done) PetscValidBoolPointer(done, 8);
7651   MatCheckPreallocated(mat, 1);
7652   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7653   else {
7654     if (done) *done = PETSC_TRUE;
7655     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7656     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7657     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7658   }
7659   PetscFunctionReturn(0);
7660 }
7661 
7662 /*@C
7663     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7664 
7665     Collective on mat
7666 
7667     Input Parameters:
7668 +   mat - the matrix
7669 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7670 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7671                 symmetrized
7672 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7673                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7674                  always used.
7675 .   n - number of columns in the (possibly compressed) matrix
7676 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7677 -   ja - the row indices
7678 
7679     Output Parameters:
7680 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7681 
7682     Level: developer
7683 
7684 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7685 @*/
7686 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7687   PetscFunctionBegin;
7688   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7689   PetscValidType(mat, 1);
7690   PetscValidIntPointer(n, 5);
7691   if (ia) PetscValidPointer(ia, 6);
7692   if (ja) PetscValidPointer(ja, 7);
7693   PetscValidBoolPointer(done, 8);
7694   MatCheckPreallocated(mat, 1);
7695   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7696   else {
7697     *done = PETSC_TRUE;
7698     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7699   }
7700   PetscFunctionReturn(0);
7701 }
7702 
7703 /*@C
7704     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7705 
7706     Collective on mat
7707 
7708     Input Parameters:
7709 +   mat - the matrix
7710 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7711 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7712 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7713                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7714                  always used.
7715 .   n - size of (possibly compressed) matrix
7716 .   ia - the row pointers
7717 -   ja - the column indices
7718 
7719     Output Parameters:
7720 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7721 
7722     Note:
7723     This routine zeros out n, ia, and ja. This is to prevent accidental
7724     us of the array after it has been restored. If you pass NULL, it will
7725     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7726 
7727     Level: developer
7728 
7729 .seealso: `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7730 @*/
7731 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7732   PetscFunctionBegin;
7733   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7734   PetscValidType(mat, 1);
7735   if (ia) PetscValidPointer(ia, 6);
7736   if (ja) PetscValidPointer(ja, 7);
7737   if (done) PetscValidBoolPointer(done, 8);
7738   MatCheckPreallocated(mat, 1);
7739 
7740   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
7741   else {
7742     if (done) *done = PETSC_TRUE;
7743     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7744     if (n) *n = 0;
7745     if (ia) *ia = NULL;
7746     if (ja) *ja = NULL;
7747   }
7748   PetscFunctionReturn(0);
7749 }
7750 
7751 /*@C
7752     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
7753 
7754     Collective on Mat
7755 
7756     Input Parameters:
7757 +   mat - the matrix
7758 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7759 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7760 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7761                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7762                  always used.
7763 
7764     Output Parameters:
7765 +   n - size of (possibly compressed) matrix
7766 .   ia - the column pointers
7767 .   ja - the row indices
7768 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7769 
7770     Level: developer
7771 
7772 .seealso: `MatGetColumnIJ()`, `MatRestoreRowIJ()`
7773 @*/
7774 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done) {
7775   PetscFunctionBegin;
7776   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7777   PetscValidType(mat, 1);
7778   if (ia) PetscValidPointer(ia, 6);
7779   if (ja) PetscValidPointer(ja, 7);
7780   PetscValidBoolPointer(done, 8);
7781   MatCheckPreallocated(mat, 1);
7782 
7783   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
7784   else {
7785     *done = PETSC_TRUE;
7786     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7787     if (n) *n = 0;
7788     if (ia) *ia = NULL;
7789     if (ja) *ja = NULL;
7790   }
7791   PetscFunctionReturn(0);
7792 }
7793 
7794 /*@C
7795     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
7796 
7797     Collective on mat
7798 
7799     Input Parameters:
7800 +   mat - the matrix
7801 .   ncolors - max color value
7802 .   n   - number of entries in colorarray
7803 -   colorarray - array indicating color for each column
7804 
7805     Output Parameters:
7806 .   iscoloring - coloring generated using colorarray information
7807 
7808     Level: developer
7809 
7810 .seealso: `MatGetRowIJ()`, `MatGetColumnIJ()`
7811 @*/
7812 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring) {
7813   PetscFunctionBegin;
7814   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7815   PetscValidType(mat, 1);
7816   PetscValidIntPointer(colorarray, 4);
7817   PetscValidPointer(iscoloring, 5);
7818   MatCheckPreallocated(mat, 1);
7819 
7820   if (!mat->ops->coloringpatch) {
7821     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
7822   } else {
7823     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
7824   }
7825   PetscFunctionReturn(0);
7826 }
7827 
7828 /*@
7829    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
7830 
7831    Logically Collective on mat
7832 
7833    Input Parameter:
7834 .  mat - the factored matrix to be reset
7835 
7836    Notes:
7837    This routine should be used only with factored matrices formed by in-place
7838    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
7839    format).  This option can save memory, for example, when solving nonlinear
7840    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
7841    ILU(0) preconditioner.
7842 
7843    Note that one can specify in-place ILU(0) factorization by calling
7844 .vb
7845      PCType(pc,PCILU);
7846      PCFactorSeUseInPlace(pc);
7847 .ve
7848    or by using the options -pc_type ilu -pc_factor_in_place
7849 
7850    In-place factorization ILU(0) can also be used as a local
7851    solver for the blocks within the block Jacobi or additive Schwarz
7852    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
7853    for details on setting local solver options.
7854 
7855    Most users should employ the `KSP` interface for linear solvers
7856    instead of working directly with matrix algebra routines such as this.
7857    See, e.g., `KSPCreate()`.
7858 
7859    Level: developer
7860 
7861 .seealso: `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
7862 @*/
7863 PetscErrorCode MatSetUnfactored(Mat mat) {
7864   PetscFunctionBegin;
7865   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7866   PetscValidType(mat, 1);
7867   MatCheckPreallocated(mat, 1);
7868   mat->factortype = MAT_FACTOR_NONE;
7869   if (!mat->ops->setunfactored) PetscFunctionReturn(0);
7870   PetscUseTypeMethod(mat, setunfactored);
7871   PetscFunctionReturn(0);
7872 }
7873 
7874 /*MC
7875     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
7876 
7877     Synopsis:
7878     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7879 
7880     Not collective
7881 
7882     Input Parameter:
7883 .   x - matrix
7884 
7885     Output Parameters:
7886 +   xx_v - the Fortran pointer to the array
7887 -   ierr - error code
7888 
7889     Example of Usage:
7890 .vb
7891       PetscScalar, pointer xx_v(:,:)
7892       ....
7893       call MatDenseGetArrayF90(x,xx_v,ierr)
7894       a = xx_v(3)
7895       call MatDenseRestoreArrayF90(x,xx_v,ierr)
7896 .ve
7897 
7898     Level: advanced
7899 
7900 .seealso: `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
7901 
7902 M*/
7903 
7904 /*MC
7905     MatDenseRestoreArrayF90 - Restores a matrix array that has been
7906     accessed with `MatDenseGetArrayF90()`.
7907 
7908     Synopsis:
7909     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
7910 
7911     Not collective
7912 
7913     Input Parameters:
7914 +   x - matrix
7915 -   xx_v - the Fortran90 pointer to the array
7916 
7917     Output Parameter:
7918 .   ierr - error code
7919 
7920     Example of Usage:
7921 .vb
7922        PetscScalar, pointer xx_v(:,:)
7923        ....
7924        call MatDenseGetArrayF90(x,xx_v,ierr)
7925        a = xx_v(3)
7926        call MatDenseRestoreArrayF90(x,xx_v,ierr)
7927 .ve
7928 
7929     Level: advanced
7930 
7931 .seealso: `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
7932 
7933 M*/
7934 
7935 /*MC
7936     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
7937 
7938     Synopsis:
7939     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7940 
7941     Not collective
7942 
7943     Input Parameter:
7944 .   x - matrix
7945 
7946     Output Parameters:
7947 +   xx_v - the Fortran pointer to the array
7948 -   ierr - error code
7949 
7950     Example of Usage:
7951 .vb
7952       PetscScalar, pointer xx_v(:)
7953       ....
7954       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7955       a = xx_v(3)
7956       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7957 .ve
7958 
7959     Level: advanced
7960 
7961 .seealso: `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
7962 
7963 M*/
7964 
7965 /*MC
7966     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
7967     accessed with `MatSeqAIJGetArrayF90()`.
7968 
7969     Synopsis:
7970     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
7971 
7972     Not collective
7973 
7974     Input Parameters:
7975 +   x - matrix
7976 -   xx_v - the Fortran90 pointer to the array
7977 
7978     Output Parameter:
7979 .   ierr - error code
7980 
7981     Example of Usage:
7982 .vb
7983        PetscScalar, pointer xx_v(:)
7984        ....
7985        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
7986        a = xx_v(3)
7987        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
7988 .ve
7989 
7990     Level: advanced
7991 
7992 .seealso: `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
7993 
7994 M*/
7995 
7996 /*@
7997     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
7998                       as the original matrix.
7999 
8000     Collective on mat
8001 
8002     Input Parameters:
8003 +   mat - the original matrix
8004 .   isrow - parallel IS containing the rows this processor should obtain
8005 .   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.
8006 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8007 
8008     Output Parameter:
8009 .   newmat - the new submatrix, of the same type as the old
8010 
8011     Level: advanced
8012 
8013     Notes:
8014     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8015 
8016     Some matrix types place restrictions on the row and column indices, such
8017     as that they be sorted or that they be equal to each other.
8018 
8019     The index sets may not have duplicate entries.
8020 
8021       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8022    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8023    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8024    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8025    you are finished using it.
8026 
8027     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8028     the input matrix.
8029 
8030     If iscol is NULL then all columns are obtained (not supported in Fortran).
8031 
8032    Example usage:
8033    Consider the following 8x8 matrix with 34 non-zero values, that is
8034    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8035    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8036    as follows:
8037 
8038 .vb
8039             1  2  0  |  0  3  0  |  0  4
8040     Proc0   0  5  6  |  7  0  0  |  8  0
8041             9  0 10  | 11  0  0  | 12  0
8042     -------------------------------------
8043            13  0 14  | 15 16 17  |  0  0
8044     Proc1   0 18  0  | 19 20 21  |  0  0
8045             0  0  0  | 22 23  0  | 24  0
8046     -------------------------------------
8047     Proc2  25 26 27  |  0  0 28  | 29  0
8048            30  0  0  | 31 32 33  |  0 34
8049 .ve
8050 
8051     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8052 
8053 .vb
8054             2  0  |  0  3  0  |  0
8055     Proc0   5  6  |  7  0  0  |  8
8056     -------------------------------
8057     Proc1  18  0  | 19 20 21  |  0
8058     -------------------------------
8059     Proc2  26 27  |  0  0 28  | 29
8060             0  0  | 31 32 33  |  0
8061 .ve
8062 
8063 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8064 @*/
8065 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat) {
8066   PetscMPIInt size;
8067   Mat        *local;
8068   IS          iscoltmp;
8069   PetscBool   flg;
8070 
8071   PetscFunctionBegin;
8072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8073   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8074   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8075   PetscValidPointer(newmat, 5);
8076   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8077   PetscValidType(mat, 1);
8078   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8079   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8080 
8081   MatCheckPreallocated(mat, 1);
8082   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8083 
8084   if (!iscol || isrow == iscol) {
8085     PetscBool   stride;
8086     PetscMPIInt grabentirematrix = 0, grab;
8087     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8088     if (stride) {
8089       PetscInt first, step, n, rstart, rend;
8090       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8091       if (step == 1) {
8092         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8093         if (rstart == first) {
8094           PetscCall(ISGetLocalSize(isrow, &n));
8095           if (n == rend - rstart) grabentirematrix = 1;
8096         }
8097       }
8098     }
8099     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8100     if (grab) {
8101       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8102       if (cll == MAT_INITIAL_MATRIX) {
8103         *newmat = mat;
8104         PetscCall(PetscObjectReference((PetscObject)mat));
8105       }
8106       PetscFunctionReturn(0);
8107     }
8108   }
8109 
8110   if (!iscol) {
8111     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8112   } else {
8113     iscoltmp = iscol;
8114   }
8115 
8116   /* if original matrix is on just one processor then use submatrix generated */
8117   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8118     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8119     goto setproperties;
8120   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8121     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8122     *newmat = *local;
8123     PetscCall(PetscFree(local));
8124     goto setproperties;
8125   } else if (!mat->ops->createsubmatrix) {
8126     /* Create a new matrix type that implements the operation using the full matrix */
8127     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8128     switch (cll) {
8129     case MAT_INITIAL_MATRIX: PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat)); break;
8130     case MAT_REUSE_MATRIX: PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp)); break;
8131     default: SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8132     }
8133     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8134     goto setproperties;
8135   }
8136 
8137   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8138   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8139   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8140 
8141 setproperties:
8142   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8143   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8144   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8145   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8146   PetscFunctionReturn(0);
8147 }
8148 
8149 /*@
8150    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8151 
8152    Not Collective
8153 
8154    Input Parameters:
8155 +  A - the matrix we wish to propagate options from
8156 -  B - the matrix we wish to propagate options to
8157 
8158    Level: beginner
8159 
8160    Note:
8161    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8162 
8163 .seealso: `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8164 @*/
8165 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B) {
8166   PetscFunctionBegin;
8167   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8168   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8169   B->symmetry_eternal            = A->symmetry_eternal;
8170   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8171   B->symmetric                   = A->symmetric;
8172   B->structurally_symmetric      = A->structurally_symmetric;
8173   B->spd                         = A->spd;
8174   B->hermitian                   = A->hermitian;
8175   PetscFunctionReturn(0);
8176 }
8177 
8178 /*@
8179    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8180    used during the assembly process to store values that belong to
8181    other processors.
8182 
8183    Not Collective
8184 
8185    Input Parameters:
8186 +  mat   - the matrix
8187 .  size  - the initial size of the stash.
8188 -  bsize - the initial size of the block-stash(if used).
8189 
8190    Options Database Keys:
8191 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8192 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8193 
8194    Level: intermediate
8195 
8196    Notes:
8197      The block-stash is used for values set with `MatSetValuesBlocked()` while
8198      the stash is used for values set with `MatSetValues()`
8199 
8200      Run with the option -info and look for output of the form
8201      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8202      to determine the appropriate value, MM, to use for size and
8203      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8204      to determine the value, BMM to use for bsize
8205 
8206 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8207 @*/
8208 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize) {
8209   PetscFunctionBegin;
8210   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8211   PetscValidType(mat, 1);
8212   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8213   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8214   PetscFunctionReturn(0);
8215 }
8216 
8217 /*@
8218    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8219      the matrix
8220 
8221    Neighbor-wise Collective on mat
8222 
8223    Input Parameters:
8224 +  mat   - the matrix
8225 .  x,y - the vectors
8226 -  w - where the result is stored
8227 
8228    Level: intermediate
8229 
8230    Notes:
8231     w may be the same vector as y.
8232 
8233     This allows one to use either the restriction or interpolation (its transpose)
8234     matrix to do the interpolation
8235 
8236 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8237 @*/
8238 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w) {
8239   PetscInt M, N, Ny;
8240 
8241   PetscFunctionBegin;
8242   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8243   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8244   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8245   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8246   PetscCall(MatGetSize(A, &M, &N));
8247   PetscCall(VecGetSize(y, &Ny));
8248   if (M == Ny) {
8249     PetscCall(MatMultAdd(A, x, y, w));
8250   } else {
8251     PetscCall(MatMultTransposeAdd(A, x, y, w));
8252   }
8253   PetscFunctionReturn(0);
8254 }
8255 
8256 /*@
8257    MatInterpolate - y = A*x or A'*x depending on the shape of
8258      the matrix
8259 
8260    Neighbor-wise Collective on mat
8261 
8262    Input Parameters:
8263 +  mat   - the matrix
8264 -  x,y - the vectors
8265 
8266    Level: intermediate
8267 
8268    Note:
8269     This allows one to use either the restriction or interpolation (its transpose)
8270     matrix to do the interpolation
8271 
8272 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8273 @*/
8274 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y) {
8275   PetscInt M, N, Ny;
8276 
8277   PetscFunctionBegin;
8278   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8279   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8280   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8281   PetscCall(MatGetSize(A, &M, &N));
8282   PetscCall(VecGetSize(y, &Ny));
8283   if (M == Ny) {
8284     PetscCall(MatMult(A, x, y));
8285   } else {
8286     PetscCall(MatMultTranspose(A, x, y));
8287   }
8288   PetscFunctionReturn(0);
8289 }
8290 
8291 /*@
8292    MatRestrict - y = A*x or A'*x
8293 
8294    Neighbor-wise Collective on Mat
8295 
8296    Input Parameters:
8297 +  mat   - the matrix
8298 -  x,y - the vectors
8299 
8300    Level: intermediate
8301 
8302    Note:
8303     This allows one to use either the restriction or interpolation (its transpose)
8304     matrix to do the restriction
8305 
8306 .seealso: `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8307 @*/
8308 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y) {
8309   PetscInt M, N, Ny;
8310 
8311   PetscFunctionBegin;
8312   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8313   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8314   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8315   PetscCall(MatGetSize(A, &M, &N));
8316   PetscCall(VecGetSize(y, &Ny));
8317   if (M == Ny) {
8318     PetscCall(MatMult(A, x, y));
8319   } else {
8320     PetscCall(MatMultTranspose(A, x, y));
8321   }
8322   PetscFunctionReturn(0);
8323 }
8324 
8325 /*@
8326    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8327 
8328    Neighbor-wise Collective on Mat
8329 
8330    Input Parameters:
8331 +  mat   - the matrix
8332 -  w, x - the input dense matrices
8333 
8334    Output Parameters:
8335 .  y - the output dense matrix
8336 
8337    Level: intermediate
8338 
8339    Note:
8340     This allows one to use either the restriction or interpolation (its transpose)
8341     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8342     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8343 
8344 .seealso: `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8345 @*/
8346 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y) {
8347   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8348   PetscBool trans = PETSC_TRUE;
8349   MatReuse  reuse = MAT_INITIAL_MATRIX;
8350 
8351   PetscFunctionBegin;
8352   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8353   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8354   PetscValidType(x, 2);
8355   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8356   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8357   PetscCall(MatGetSize(A, &M, &N));
8358   PetscCall(MatGetSize(x, &Mx, &Nx));
8359   if (N == Mx) trans = PETSC_FALSE;
8360   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);
8361   Mo = trans ? N : M;
8362   if (*y) {
8363     PetscCall(MatGetSize(*y, &My, &Ny));
8364     if (Mo == My && Nx == Ny) {
8365       reuse = MAT_REUSE_MATRIX;
8366     } else {
8367       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);
8368       PetscCall(MatDestroy(y));
8369     }
8370   }
8371 
8372   if (w && *y == w) { /* this is to minimize changes in PCMG */
8373     PetscBool flg;
8374 
8375     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8376     if (w) {
8377       PetscInt My, Ny, Mw, Nw;
8378 
8379       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8380       PetscCall(MatGetSize(*y, &My, &Ny));
8381       PetscCall(MatGetSize(w, &Mw, &Nw));
8382       if (!flg || My != Mw || Ny != Nw) w = NULL;
8383     }
8384     if (!w) {
8385       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8386       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8387       PetscCall(PetscLogObjectParent((PetscObject)*y, (PetscObject)w));
8388       PetscCall(PetscObjectDereference((PetscObject)w));
8389     } else {
8390       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8391     }
8392   }
8393   if (!trans) {
8394     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8395   } else {
8396     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8397   }
8398   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8399   PetscFunctionReturn(0);
8400 }
8401 
8402 /*@
8403    MatMatInterpolate - Y = A*X or A'*X
8404 
8405    Neighbor-wise Collective on Mat
8406 
8407    Input Parameters:
8408 +  mat   - the matrix
8409 -  x - the input dense matrix
8410 
8411    Output Parameters:
8412 .  y - the output dense matrix
8413 
8414    Level: intermediate
8415 
8416    Note:
8417     This allows one to use either the restriction or interpolation (its transpose)
8418     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8419     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8420 
8421 .seealso: `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8422 @*/
8423 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y) {
8424   PetscFunctionBegin;
8425   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8426   PetscFunctionReturn(0);
8427 }
8428 
8429 /*@
8430    MatMatRestrict - Y = A*X or A'*X
8431 
8432    Neighbor-wise Collective on Mat
8433 
8434    Input Parameters:
8435 +  mat   - the matrix
8436 -  x - the input dense matrix
8437 
8438    Output Parameters:
8439 .  y - the output dense matrix
8440 
8441    Level: intermediate
8442 
8443    Note:
8444     This allows one to use either the restriction or interpolation (its transpose)
8445     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8446     otherwise it will be recreated. y must be initialized to NULL if not supplied.
8447 
8448 .seealso: `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8449 @*/
8450 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y) {
8451   PetscFunctionBegin;
8452   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8453   PetscFunctionReturn(0);
8454 }
8455 
8456 /*@
8457    MatGetNullSpace - retrieves the null space of a matrix.
8458 
8459    Logically Collective on mat
8460 
8461    Input Parameters:
8462 +  mat - the matrix
8463 -  nullsp - the null space object
8464 
8465    Level: developer
8466 
8467 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8468 @*/
8469 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp) {
8470   PetscFunctionBegin;
8471   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8472   PetscValidPointer(nullsp, 2);
8473   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8474   PetscFunctionReturn(0);
8475 }
8476 
8477 /*@
8478    MatSetNullSpace - attaches a null space to a matrix.
8479 
8480    Logically Collective on mat
8481 
8482    Input Parameters:
8483 +  mat - the matrix
8484 -  nullsp - the null space object
8485 
8486    Level: advanced
8487 
8488    Notes:
8489       This null space is used by the `KSP` linear solvers to solve singular systems.
8490 
8491       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
8492 
8493       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
8494       to zero but the linear system will still be solved in a least squares sense.
8495 
8496       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8497    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).
8498    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
8499    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
8500    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).
8501    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8502 
8503     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8504     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8505     routine also automatically calls `MatSetTransposeNullSpace()`.
8506 
8507     The user should call `MatNullSpaceDestroy()`.
8508 
8509 .seealso: `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8510           `KSPSetPCSide()`
8511 @*/
8512 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp) {
8513   PetscFunctionBegin;
8514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8515   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8516   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8517   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8518   mat->nullsp = nullsp;
8519   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8520   PetscFunctionReturn(0);
8521 }
8522 
8523 /*@
8524    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8525 
8526    Logically Collective on mat
8527 
8528    Input Parameters:
8529 +  mat - the matrix
8530 -  nullsp - the null space object
8531 
8532    Level: developer
8533 
8534 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8535 @*/
8536 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp) {
8537   PetscFunctionBegin;
8538   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8539   PetscValidType(mat, 1);
8540   PetscValidPointer(nullsp, 2);
8541   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8542   PetscFunctionReturn(0);
8543 }
8544 
8545 /*@
8546    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8547 
8548    Logically Collective on mat
8549 
8550    Input Parameters:
8551 +  mat - the matrix
8552 -  nullsp - the null space object
8553 
8554    Level: advanced
8555 
8556    Notes:
8557    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8558 
8559    See `MatSetNullSpace()`
8560 
8561 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8562 @*/
8563 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp) {
8564   PetscFunctionBegin;
8565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8566   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8567   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8568   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8569   mat->transnullsp = nullsp;
8570   PetscFunctionReturn(0);
8571 }
8572 
8573 /*@
8574    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8575         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8576 
8577    Logically Collective on mat
8578 
8579    Input Parameters:
8580 +  mat - the matrix
8581 -  nullsp - the null space object
8582 
8583    Level: advanced
8584 
8585    Notes:
8586    Overwrites any previous near null space that may have been attached
8587 
8588    You can remove the null space by calling this routine with an nullsp of NULL
8589 
8590 .seealso: `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8591 @*/
8592 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp) {
8593   PetscFunctionBegin;
8594   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8595   PetscValidType(mat, 1);
8596   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8597   MatCheckPreallocated(mat, 1);
8598   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8599   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8600   mat->nearnullsp = nullsp;
8601   PetscFunctionReturn(0);
8602 }
8603 
8604 /*@
8605    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8606 
8607    Not Collective
8608 
8609    Input Parameter:
8610 .  mat - the matrix
8611 
8612    Output Parameter:
8613 .  nullsp - the null space object, NULL if not set
8614 
8615    Level: advanced
8616 
8617 .seealso: `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8618 @*/
8619 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp) {
8620   PetscFunctionBegin;
8621   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8622   PetscValidType(mat, 1);
8623   PetscValidPointer(nullsp, 2);
8624   MatCheckPreallocated(mat, 1);
8625   *nullsp = mat->nearnullsp;
8626   PetscFunctionReturn(0);
8627 }
8628 
8629 /*@C
8630    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8631 
8632    Collective on mat
8633 
8634    Input Parameters:
8635 +  mat - the matrix
8636 .  row - row/column permutation
8637 .  fill - expected fill factor >= 1.0
8638 -  level - level of fill, for ICC(k)
8639 
8640    Notes:
8641    Probably really in-place only when level of fill is zero, otherwise allocates
8642    new space to store factored matrix and deletes previous memory.
8643 
8644    Most users should employ the `KSP` interface for linear solvers
8645    instead of working directly with matrix algebra routines such as this.
8646    See, e.g., `KSPCreate()`.
8647 
8648    Level: developer
8649 
8650    Developer Note:
8651    The Fortran interface is not autogenerated as the f90
8652    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8653 
8654 .seealso: `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8655 @*/
8656 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info) {
8657   PetscFunctionBegin;
8658   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8659   PetscValidType(mat, 1);
8660   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8661   PetscValidPointer(info, 3);
8662   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8663   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8664   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8665   MatCheckPreallocated(mat, 1);
8666   PetscUseTypeMethod(mat, iccfactor, row, info);
8667   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8668   PetscFunctionReturn(0);
8669 }
8670 
8671 /*@
8672    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8673          ghosted ones.
8674 
8675    Not Collective
8676 
8677    Input Parameters:
8678 +  mat - the matrix
8679 -  diag - the diagonal values, including ghost ones
8680 
8681    Level: developer
8682 
8683    Notes:
8684     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8685 
8686     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8687 
8688 .seealso: `MatDiagonalScale()`
8689 @*/
8690 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag) {
8691   PetscMPIInt size;
8692 
8693   PetscFunctionBegin;
8694   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8695   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8696   PetscValidType(mat, 1);
8697 
8698   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8699   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8700   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8701   if (size == 1) {
8702     PetscInt n, m;
8703     PetscCall(VecGetSize(diag, &n));
8704     PetscCall(MatGetSize(mat, NULL, &m));
8705     if (m == n) {
8706       PetscCall(MatDiagonalScale(mat, NULL, diag));
8707     } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
8708   } else {
8709     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
8710   }
8711   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
8712   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8713   PetscFunctionReturn(0);
8714 }
8715 
8716 /*@
8717    MatGetInertia - Gets the inertia from a factored matrix
8718 
8719    Collective on mat
8720 
8721    Input Parameter:
8722 .  mat - the matrix
8723 
8724    Output Parameters:
8725 +   nneg - number of negative eigenvalues
8726 .   nzero - number of zero eigenvalues
8727 -   npos - number of positive eigenvalues
8728 
8729    Level: advanced
8730 
8731    Note:
8732     Matrix must have been factored by `MatCholeskyFactor()`
8733 
8734 .seealso: `MatGetFactor()`, `MatCholeskyFactor()`
8735 @*/
8736 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos) {
8737   PetscFunctionBegin;
8738   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8739   PetscValidType(mat, 1);
8740   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8741   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
8742   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
8743   PetscFunctionReturn(0);
8744 }
8745 
8746 /* ----------------------------------------------------------------*/
8747 /*@C
8748    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
8749 
8750    Neighbor-wise Collective on mat
8751 
8752    Input Parameters:
8753 +  mat - the factored matrix obtained with `MatGetFactor()`
8754 -  b - the right-hand-side vectors
8755 
8756    Output Parameter:
8757 .  x - the result vectors
8758 
8759    Note:
8760    The vectors b and x cannot be the same.  I.e., one cannot
8761    call `MatSolves`(A,x,x).
8762 
8763    Level: developer
8764 
8765 .seealso: `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
8766 @*/
8767 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x) {
8768   PetscFunctionBegin;
8769   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8770   PetscValidType(mat, 1);
8771   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
8772   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
8773   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(0);
8774 
8775   MatCheckPreallocated(mat, 1);
8776   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
8777   PetscUseTypeMethod(mat, solves, b, x);
8778   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
8779   PetscFunctionReturn(0);
8780 }
8781 
8782 /*@
8783    MatIsSymmetric - Test whether a matrix is symmetric
8784 
8785    Collective on mat
8786 
8787    Input Parameters:
8788 +  A - the matrix to test
8789 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
8790 
8791    Output Parameters:
8792 .  flg - the result
8793 
8794    Notes:
8795     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8796 
8797     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
8798 
8799     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8800     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8801 
8802    Level: intermediate
8803 
8804 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
8805           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8806 @*/
8807 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg) {
8808   PetscFunctionBegin;
8809   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8810   PetscValidBoolPointer(flg, 3);
8811 
8812   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8813   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8814   else {
8815     if (!A->ops->issymmetric) {
8816       MatType mattype;
8817       PetscCall(MatGetType(A, &mattype));
8818       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
8819     }
8820     PetscUseTypeMethod(A, issymmetric, tol, flg);
8821     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
8822   }
8823   PetscFunctionReturn(0);
8824 }
8825 
8826 /*@
8827    MatIsHermitian - Test whether a matrix is Hermitian
8828 
8829    Collective on Mat
8830 
8831    Input Parameters:
8832 +  A - the matrix to test
8833 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
8834 
8835    Output Parameters:
8836 .  flg - the result
8837 
8838    Level: intermediate
8839 
8840    Notes:
8841     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
8842 
8843     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
8844 
8845     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8846     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
8847 
8848 .seealso: `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
8849           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
8850 @*/
8851 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg) {
8852   PetscFunctionBegin;
8853   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8854   PetscValidBoolPointer(flg, 3);
8855 
8856   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
8857   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
8858   else {
8859     if (!A->ops->ishermitian) {
8860       MatType mattype;
8861       PetscCall(MatGetType(A, &mattype));
8862       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
8863     }
8864     PetscUseTypeMethod(A, ishermitian, tol, flg);
8865     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
8866   }
8867   PetscFunctionReturn(0);
8868 }
8869 
8870 /*@
8871    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
8872 
8873    Not Collective
8874 
8875    Input Parameter:
8876 .  A - the matrix to check
8877 
8878    Output Parameters:
8879 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
8880 -  flg - the result (only valid if set is `PETSC_TRUE`)
8881 
8882    Level: advanced
8883 
8884    Notes:
8885    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
8886    if you want it explicitly checked
8887 
8888     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
8889     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8890 
8891 .seealso: `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8892 @*/
8893 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) {
8894   PetscFunctionBegin;
8895   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8896   PetscValidBoolPointer(set, 2);
8897   PetscValidBoolPointer(flg, 3);
8898   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
8899     *set = PETSC_TRUE;
8900     *flg = PetscBool3ToBool(A->symmetric);
8901   } else {
8902     *set = PETSC_FALSE;
8903   }
8904   PetscFunctionReturn(0);
8905 }
8906 
8907 /*@
8908    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
8909 
8910    Not Collective
8911 
8912    Input Parameter:
8913 .  A - the matrix to check
8914 
8915    Output Parameters:
8916 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
8917 -  flg - the result (only valid if set is `PETSC_TRUE`)
8918 
8919    Level: advanced
8920 
8921    Notes:
8922    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
8923 
8924    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
8925    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
8926 
8927 .seealso: `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
8928 @*/
8929 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg) {
8930   PetscFunctionBegin;
8931   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8932   PetscValidBoolPointer(set, 2);
8933   PetscValidBoolPointer(flg, 3);
8934   if (A->spd != PETSC_BOOL3_UNKNOWN) {
8935     *set = PETSC_TRUE;
8936     *flg = PetscBool3ToBool(A->spd);
8937   } else {
8938     *set = PETSC_FALSE;
8939   }
8940   PetscFunctionReturn(0);
8941 }
8942 
8943 /*@
8944    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
8945 
8946    Not Collective
8947 
8948    Input Parameter:
8949 .  A - the matrix to check
8950 
8951    Output Parameters:
8952 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
8953 -  flg - the result (only valid if set is `PETSC_TRUE`)
8954 
8955    Level: advanced
8956 
8957    Notes:
8958    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
8959    if you want it explicitly checked
8960 
8961    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
8962    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8963 
8964 .seealso: `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
8965 @*/
8966 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg) {
8967   PetscFunctionBegin;
8968   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8969   PetscValidBoolPointer(set, 2);
8970   PetscValidBoolPointer(flg, 3);
8971   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
8972     *set = PETSC_TRUE;
8973     *flg = PetscBool3ToBool(A->hermitian);
8974   } else {
8975     *set = PETSC_FALSE;
8976   }
8977   PetscFunctionReturn(0);
8978 }
8979 
8980 /*@
8981    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
8982 
8983    Collective on Mat
8984 
8985    Input Parameter:
8986 .  A - the matrix to test
8987 
8988    Output Parameters:
8989 .  flg - the result
8990 
8991    Notes:
8992    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
8993 
8994    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
8995    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
8996 
8997    Level: intermediate
8998 
8999 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9000 @*/
9001 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg) {
9002   PetscFunctionBegin;
9003   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9004   PetscValidBoolPointer(flg, 2);
9005   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9006     *flg = PetscBool3ToBool(A->structurally_symmetric);
9007   } else {
9008     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9009     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9010   }
9011   PetscFunctionReturn(0);
9012 }
9013 
9014 /*@
9015    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9016 
9017    Not Collective
9018 
9019    Input Parameter:
9020 .  A - the matrix to check
9021 
9022    Output Parameters:
9023 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9024 -  flg - the result (only valid if set is PETSC_TRUE)
9025 
9026    Level: advanced
9027 
9028    Notes:
9029    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
9030    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9031 
9032    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9033 
9034 .seealso: `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9035 @*/
9036 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg) {
9037   PetscFunctionBegin;
9038   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9039   PetscValidBoolPointer(set, 2);
9040   PetscValidBoolPointer(flg, 3);
9041   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9042     *set = PETSC_TRUE;
9043     *flg = PetscBool3ToBool(A->structurally_symmetric);
9044   } else {
9045     *set = PETSC_FALSE;
9046   }
9047   PetscFunctionReturn(0);
9048 }
9049 
9050 /*@
9051    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9052        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9053 
9054     Not collective
9055 
9056    Input Parameter:
9057 .   mat - the matrix
9058 
9059    Output Parameters:
9060 +   nstash   - the size of the stash
9061 .   reallocs - the number of additional mallocs incurred.
9062 .   bnstash   - the size of the block stash
9063 -   breallocs - the number of additional mallocs incurred.in the block stash
9064 
9065    Level: advanced
9066 
9067 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9068 @*/
9069 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs) {
9070   PetscFunctionBegin;
9071   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9072   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9073   PetscFunctionReturn(0);
9074 }
9075 
9076 /*@C
9077    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9078    parallel layout, `PetscLayout` for rows and columns
9079 
9080    Collective on mat
9081 
9082    Input Parameter:
9083 .  mat - the matrix
9084 
9085    Output Parameters:
9086 +   right - (optional) vector that the matrix can be multiplied against
9087 -   left - (optional) vector that the matrix vector product can be stored in
9088 
9089    Notes:
9090     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()`.
9091 
9092     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9093 
9094   Level: advanced
9095 
9096 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9097 @*/
9098 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left) {
9099   PetscFunctionBegin;
9100   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9101   PetscValidType(mat, 1);
9102   if (mat->ops->getvecs) {
9103     PetscUseTypeMethod(mat, getvecs, right, left);
9104   } else {
9105     PetscInt rbs, cbs;
9106     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9107     if (right) {
9108       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9109       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9110       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9111       PetscCall(VecSetBlockSize(*right, cbs));
9112       PetscCall(VecSetType(*right, mat->defaultvectype));
9113 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9114       if (mat->boundtocpu && mat->bindingpropagates) {
9115         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9116         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9117       }
9118 #endif
9119       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9120     }
9121     if (left) {
9122       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9123       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9124       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9125       PetscCall(VecSetBlockSize(*left, rbs));
9126       PetscCall(VecSetType(*left, mat->defaultvectype));
9127 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9128       if (mat->boundtocpu && mat->bindingpropagates) {
9129         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9130         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9131       }
9132 #endif
9133       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9134     }
9135   }
9136   PetscFunctionReturn(0);
9137 }
9138 
9139 /*@C
9140    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9141      with default values.
9142 
9143    Not Collective
9144 
9145    Input Parameters:
9146 .    info - the `MatFactorInfo` data structure
9147 
9148    Notes:
9149     The solvers are generally used through the `KSP` and `PC` objects, for example
9150           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9151 
9152     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9153 
9154    Level: developer
9155 
9156    Developer Note:
9157    The Fortran interface is not autogenerated as the f90
9158    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9159 
9160 .seealso: `MatGetFactor()`, `MatFactorInfo`
9161 @*/
9162 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info) {
9163   PetscFunctionBegin;
9164   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9165   PetscFunctionReturn(0);
9166 }
9167 
9168 /*@
9169    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9170 
9171    Collective on mat
9172 
9173    Input Parameters:
9174 +  mat - the factored matrix
9175 -  is - the index set defining the Schur indices (0-based)
9176 
9177    Notes:
9178     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9179 
9180    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9181 
9182    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9183 
9184    Level: advanced
9185 
9186 .seealso: `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9187           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9188 
9189 @*/
9190 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is) {
9191   PetscErrorCode (*f)(Mat, IS);
9192 
9193   PetscFunctionBegin;
9194   PetscValidType(mat, 1);
9195   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9196   PetscValidType(is, 2);
9197   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9198   PetscCheckSameComm(mat, 1, is, 2);
9199   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9200   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9201   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9202   PetscCall(MatDestroy(&mat->schur));
9203   PetscCall((*f)(mat, is));
9204   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9205   PetscFunctionReturn(0);
9206 }
9207 
9208 /*@
9209   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9210 
9211    Logically Collective on mat
9212 
9213    Input Parameters:
9214 +  F - the factored matrix obtained by calling `MatGetFactor()`
9215 .  S - location where to return the Schur complement, can be NULL
9216 -  status - the status of the Schur complement matrix, can be NULL
9217 
9218    Notes:
9219    You must call `MatFactorSetSchurIS()` before calling this routine.
9220 
9221    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9222 
9223    The routine provides a copy of the Schur matrix stored within the solver data structures.
9224    The caller must destroy the object when it is no longer needed.
9225    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9226 
9227    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)
9228 
9229    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9230 
9231    Developer Note:
9232     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9233    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9234 
9235    Level: advanced
9236 
9237 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9238 @*/
9239 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) {
9240   PetscFunctionBegin;
9241   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9242   if (S) PetscValidPointer(S, 2);
9243   if (status) PetscValidPointer(status, 3);
9244   if (S) {
9245     PetscErrorCode (*f)(Mat, Mat *);
9246 
9247     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9248     if (f) {
9249       PetscCall((*f)(F, S));
9250     } else {
9251       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9252     }
9253   }
9254   if (status) *status = F->schur_status;
9255   PetscFunctionReturn(0);
9256 }
9257 
9258 /*@
9259   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9260 
9261    Logically Collective on mat
9262 
9263    Input Parameters:
9264 +  F - the factored matrix obtained by calling `MatGetFactor()`
9265 .  *S - location where to return the Schur complement, can be NULL
9266 -  status - the status of the Schur complement matrix, can be NULL
9267 
9268    Notes:
9269    You must call `MatFactorSetSchurIS()` before calling this routine.
9270 
9271    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9272 
9273    The routine returns a the Schur Complement stored within the data strutures of the solver.
9274 
9275    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9276 
9277    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9278 
9279    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9280 
9281    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9282 
9283    Level: advanced
9284 
9285 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9286 @*/
9287 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status) {
9288   PetscFunctionBegin;
9289   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9290   if (S) PetscValidPointer(S, 2);
9291   if (status) PetscValidPointer(status, 3);
9292   if (S) *S = F->schur;
9293   if (status) *status = F->schur_status;
9294   PetscFunctionReturn(0);
9295 }
9296 
9297 /*@
9298   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9299 
9300    Logically Collective on mat
9301 
9302    Input Parameters:
9303 +  F - the factored matrix obtained by calling `MatGetFactor()`
9304 .  *S - location where the Schur complement is stored
9305 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9306 
9307    Level: advanced
9308 
9309 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9310 @*/
9311 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status) {
9312   PetscFunctionBegin;
9313   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9314   if (S) {
9315     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9316     *S = NULL;
9317   }
9318   F->schur_status = status;
9319   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9320   PetscFunctionReturn(0);
9321 }
9322 
9323 /*@
9324   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9325 
9326    Logically Collective on mat
9327 
9328    Input Parameters:
9329 +  F - the factored matrix obtained by calling `MatGetFactor()`
9330 .  rhs - location where the right hand side of the Schur complement system is stored
9331 -  sol - location where the solution of the Schur complement system has to be returned
9332 
9333    Notes:
9334    The sizes of the vectors should match the size of the Schur complement
9335 
9336    Must be called after `MatFactorSetSchurIS()`
9337 
9338    Level: advanced
9339 
9340 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9341 @*/
9342 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol) {
9343   PetscFunctionBegin;
9344   PetscValidType(F, 1);
9345   PetscValidType(rhs, 2);
9346   PetscValidType(sol, 3);
9347   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9348   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9349   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9350   PetscCheckSameComm(F, 1, rhs, 2);
9351   PetscCheckSameComm(F, 1, sol, 3);
9352   PetscCall(MatFactorFactorizeSchurComplement(F));
9353   switch (F->schur_status) {
9354   case MAT_FACTOR_SCHUR_FACTORED: PetscCall(MatSolveTranspose(F->schur, rhs, sol)); break;
9355   case MAT_FACTOR_SCHUR_INVERTED: PetscCall(MatMultTranspose(F->schur, rhs, sol)); break;
9356   default: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9357   }
9358   PetscFunctionReturn(0);
9359 }
9360 
9361 /*@
9362   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9363 
9364    Logically Collective on mat
9365 
9366    Input Parameters:
9367 +  F - the factored matrix obtained by calling `MatGetFactor()`
9368 .  rhs - location where the right hand side of the Schur complement system is stored
9369 -  sol - location where the solution of the Schur complement system has to be returned
9370 
9371    Notes:
9372    The sizes of the vectors should match the size of the Schur complement
9373 
9374    Must be called after `MatFactorSetSchurIS()`
9375 
9376    Level: advanced
9377 
9378 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9379 @*/
9380 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol) {
9381   PetscFunctionBegin;
9382   PetscValidType(F, 1);
9383   PetscValidType(rhs, 2);
9384   PetscValidType(sol, 3);
9385   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9386   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9387   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9388   PetscCheckSameComm(F, 1, rhs, 2);
9389   PetscCheckSameComm(F, 1, sol, 3);
9390   PetscCall(MatFactorFactorizeSchurComplement(F));
9391   switch (F->schur_status) {
9392   case MAT_FACTOR_SCHUR_FACTORED: PetscCall(MatSolve(F->schur, rhs, sol)); break;
9393   case MAT_FACTOR_SCHUR_INVERTED: PetscCall(MatMult(F->schur, rhs, sol)); break;
9394   default: SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9395   }
9396   PetscFunctionReturn(0);
9397 }
9398 
9399 /*@
9400   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9401 
9402    Logically Collective on F
9403 
9404    Input Parameters:
9405 .  F - the factored matrix obtained by calling `MatGetFactor()`
9406 
9407    Notes:
9408     Must be called after `MatFactorSetSchurIS()`.
9409 
9410    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9411 
9412    Level: advanced
9413 
9414 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9415 @*/
9416 PetscErrorCode MatFactorInvertSchurComplement(Mat F) {
9417   PetscFunctionBegin;
9418   PetscValidType(F, 1);
9419   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9420   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(0);
9421   PetscCall(MatFactorFactorizeSchurComplement(F));
9422   PetscCall(MatFactorInvertSchurComplement_Private(F));
9423   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9424   PetscFunctionReturn(0);
9425 }
9426 
9427 /*@
9428   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9429 
9430    Logically Collective on mat
9431 
9432    Input Parameters:
9433 .  F - the factored matrix obtained by calling `MatGetFactor()`
9434 
9435    Note:
9436     Must be called after `MatFactorSetSchurIS()`
9437 
9438    Level: advanced
9439 
9440 .seealso: `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9441 @*/
9442 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F) {
9443   PetscFunctionBegin;
9444   PetscValidType(F, 1);
9445   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9446   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(0);
9447   PetscCall(MatFactorFactorizeSchurComplement_Private(F));
9448   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9449   PetscFunctionReturn(0);
9450 }
9451 
9452 /*@
9453    MatPtAP - Creates the matrix product C = P^T * A * P
9454 
9455    Neighbor-wise Collective on A
9456 
9457    Input Parameters:
9458 +  A - the matrix
9459 .  P - the projection matrix
9460 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9461 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9462           if the result is a dense matrix this is irrelevant
9463 
9464    Output Parameters:
9465 .  C - the product matrix
9466 
9467    Notes:
9468    C will be created and must be destroyed by the user with `MatDestroy()`.
9469 
9470    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9471 
9472    Developer Note:
9473    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9474 
9475    Level: intermediate
9476 
9477 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9478 @*/
9479 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C) {
9480   PetscFunctionBegin;
9481   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9482   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9483 
9484   if (scall == MAT_INITIAL_MATRIX) {
9485     PetscCall(MatProductCreate(A, P, NULL, C));
9486     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9487     PetscCall(MatProductSetAlgorithm(*C, "default"));
9488     PetscCall(MatProductSetFill(*C, fill));
9489 
9490     (*C)->product->api_user = PETSC_TRUE;
9491     PetscCall(MatProductSetFromOptions(*C));
9492     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);
9493     PetscCall(MatProductSymbolic(*C));
9494   } else { /* scall == MAT_REUSE_MATRIX */
9495     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9496   }
9497 
9498   PetscCall(MatProductNumeric(*C));
9499   (*C)->symmetric = A->symmetric;
9500   (*C)->spd       = A->spd;
9501   PetscFunctionReturn(0);
9502 }
9503 
9504 /*@
9505    MatRARt - Creates the matrix product C = R * A * R^T
9506 
9507    Neighbor-wise Collective on A
9508 
9509    Input Parameters:
9510 +  A - the matrix
9511 .  R - the projection matrix
9512 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9513 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9514           if the result is a dense matrix this is irrelevant
9515 
9516    Output Parameters:
9517 .  C - the product matrix
9518 
9519    Notes:
9520    C will be created and must be destroyed by the user with `MatDestroy()`.
9521 
9522    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9523 
9524    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9525    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9526    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9527    We recommend using MatPtAP().
9528 
9529    Level: intermediate
9530 
9531 .seealso: `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9532 @*/
9533 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C) {
9534   PetscFunctionBegin;
9535   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9536   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9537 
9538   if (scall == MAT_INITIAL_MATRIX) {
9539     PetscCall(MatProductCreate(A, R, NULL, C));
9540     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9541     PetscCall(MatProductSetAlgorithm(*C, "default"));
9542     PetscCall(MatProductSetFill(*C, fill));
9543 
9544     (*C)->product->api_user = PETSC_TRUE;
9545     PetscCall(MatProductSetFromOptions(*C));
9546     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);
9547     PetscCall(MatProductSymbolic(*C));
9548   } else { /* scall == MAT_REUSE_MATRIX */
9549     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9550   }
9551 
9552   PetscCall(MatProductNumeric(*C));
9553   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9554   PetscFunctionReturn(0);
9555 }
9556 
9557 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C) {
9558   PetscFunctionBegin;
9559   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9560 
9561   if (scall == MAT_INITIAL_MATRIX) {
9562     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9563     PetscCall(MatProductCreate(A, B, NULL, C));
9564     PetscCall(MatProductSetType(*C, ptype));
9565     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9566     PetscCall(MatProductSetFill(*C, fill));
9567 
9568     (*C)->product->api_user = PETSC_TRUE;
9569     PetscCall(MatProductSetFromOptions(*C));
9570     PetscCall(MatProductSymbolic(*C));
9571   } else { /* scall == MAT_REUSE_MATRIX */
9572     Mat_Product *product = (*C)->product;
9573     PetscBool    isdense;
9574 
9575     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9576     if (isdense && product && product->type != ptype) {
9577       PetscCall(MatProductClear(*C));
9578       product = NULL;
9579     }
9580     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9581     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9582       if (isdense) {
9583         PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9584         product           = (*C)->product;
9585         product->fill     = fill;
9586         product->api_user = PETSC_TRUE;
9587         product->clear    = PETSC_TRUE;
9588 
9589         PetscCall(MatProductSetType(*C, ptype));
9590         PetscCall(MatProductSetFromOptions(*C));
9591         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);
9592         PetscCall(MatProductSymbolic(*C));
9593       } else SETERRQ(PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9594     } else { /* user may change input matrices A or B when REUSE */
9595       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9596     }
9597   }
9598   PetscCall(MatProductNumeric(*C));
9599   PetscFunctionReturn(0);
9600 }
9601 
9602 /*@
9603    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9604 
9605    Neighbor-wise Collective on A
9606 
9607    Input Parameters:
9608 +  A - the left matrix
9609 .  B - the right matrix
9610 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9611 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9612           if the result is a dense matrix this is irrelevant
9613 
9614    Output Parameters:
9615 .  C - the product matrix
9616 
9617    Notes:
9618    Unless scall is `MAT_REUSE_MATRIX` C will be created.
9619 
9620    `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
9621    call to this function with `MAT_INITIAL_MATRIX`.
9622 
9623    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
9624 
9625    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`,
9626    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
9627 
9628    Example of Usage:
9629 .vb
9630      MatProductCreate(A,B,NULL,&C);
9631      MatProductSetType(C,MATPRODUCT_AB);
9632      MatProductSymbolic(C);
9633      MatProductNumeric(C); // compute C=A * B
9634      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
9635      MatProductNumeric(C);
9636      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
9637      MatProductNumeric(C);
9638 .ve
9639 
9640    Level: intermediate
9641 
9642 .seealso: `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
9643 @*/
9644 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9645   PetscFunctionBegin;
9646   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
9647   PetscFunctionReturn(0);
9648 }
9649 
9650 /*@
9651    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
9652 
9653    Neighbor-wise Collective on A
9654 
9655    Input Parameters:
9656 +  A - the left matrix
9657 .  B - the right matrix
9658 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9659 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9660 
9661    Output Parameters:
9662 .  C - the product matrix
9663 
9664    Notes:
9665    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9666 
9667    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
9668 
9669    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9670    actually needed.
9671 
9672    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
9673    and for pairs of `MATMPIDENSE` matrices.
9674 
9675    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
9676 
9677    Options Database Keys:
9678 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
9679               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
9680               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
9681 
9682    Level: intermediate
9683 
9684 .seealso: `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
9685 @*/
9686 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9687   PetscFunctionBegin;
9688   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
9689   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9690   PetscFunctionReturn(0);
9691 }
9692 
9693 /*@
9694    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
9695 
9696    Neighbor-wise Collective on A
9697 
9698    Input Parameters:
9699 +  A - the left matrix
9700 .  B - the right matrix
9701 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9702 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
9703 
9704    Output Parameters:
9705 .  C - the product matrix
9706 
9707    Notes:
9708    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
9709 
9710    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
9711 
9712    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
9713 
9714    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9715    actually needed.
9716 
9717    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
9718    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
9719 
9720    Level: intermediate
9721 
9722 .seealso: `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
9723 @*/
9724 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C) {
9725   PetscFunctionBegin;
9726   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
9727   PetscFunctionReturn(0);
9728 }
9729 
9730 /*@
9731    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
9732 
9733    Neighbor-wise Collective on A
9734 
9735    Input Parameters:
9736 +  A - the left matrix
9737 .  B - the middle matrix
9738 .  C - the right matrix
9739 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9740 -  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
9741           if the result is a dense matrix this is irrelevant
9742 
9743    Output Parameters:
9744 .  D - the product matrix
9745 
9746    Notes:
9747    Unless scall is `MAT_REUSE_MATRIX` D will be created.
9748 
9749    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
9750 
9751    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
9752 
9753    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
9754    actually needed.
9755 
9756    If you have many matrices with the same non-zero structure to multiply, you
9757    should use `MAT_REUSE_MATRIX` in all calls but the first
9758 
9759    Level: intermediate
9760 
9761 .seealso: `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
9762 @*/
9763 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D) {
9764   PetscFunctionBegin;
9765   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
9766   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9767 
9768   if (scall == MAT_INITIAL_MATRIX) {
9769     PetscCall(MatProductCreate(A, B, C, D));
9770     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
9771     PetscCall(MatProductSetAlgorithm(*D, "default"));
9772     PetscCall(MatProductSetFill(*D, fill));
9773 
9774     (*D)->product->api_user = PETSC_TRUE;
9775     PetscCall(MatProductSetFromOptions(*D));
9776     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,
9777                ((PetscObject)C)->type_name);
9778     PetscCall(MatProductSymbolic(*D));
9779   } else { /* user may change input matrices when REUSE */
9780     PetscCall(MatProductReplaceMats(A, B, C, *D));
9781   }
9782   PetscCall(MatProductNumeric(*D));
9783   PetscFunctionReturn(0);
9784 }
9785 
9786 /*@
9787    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
9788 
9789    Collective on mat
9790 
9791    Input Parameters:
9792 +  mat - the matrix
9793 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
9794 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
9795 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9796 
9797    Output Parameter:
9798 .  matredundant - redundant matrix
9799 
9800    Notes:
9801    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
9802    original matrix has not changed from that last call to MatCreateRedundantMatrix().
9803 
9804    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
9805    calling it.
9806 
9807    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
9808 
9809    Level: advanced
9810 
9811 .seealso: `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
9812 @*/
9813 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant) {
9814   MPI_Comm       comm;
9815   PetscMPIInt    size;
9816   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
9817   Mat_Redundant *redund     = NULL;
9818   PetscSubcomm   psubcomm   = NULL;
9819   MPI_Comm       subcomm_in = subcomm;
9820   Mat           *matseq;
9821   IS             isrow, iscol;
9822   PetscBool      newsubcomm = PETSC_FALSE;
9823 
9824   PetscFunctionBegin;
9825   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9826   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
9827     PetscValidPointer(*matredundant, 5);
9828     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
9829   }
9830 
9831   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9832   if (size == 1 || nsubcomm == 1) {
9833     if (reuse == MAT_INITIAL_MATRIX) {
9834       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
9835     } else {
9836       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");
9837       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
9838     }
9839     PetscFunctionReturn(0);
9840   }
9841 
9842   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
9843   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
9844   MatCheckPreallocated(mat, 1);
9845 
9846   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
9847   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
9848     /* create psubcomm, then get subcomm */
9849     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
9850     PetscCallMPI(MPI_Comm_size(comm, &size));
9851     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
9852 
9853     PetscCall(PetscSubcommCreate(comm, &psubcomm));
9854     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
9855     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
9856     PetscCall(PetscSubcommSetFromOptions(psubcomm));
9857     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
9858     newsubcomm = PETSC_TRUE;
9859     PetscCall(PetscSubcommDestroy(&psubcomm));
9860   }
9861 
9862   /* get isrow, iscol and a local sequential matrix matseq[0] */
9863   if (reuse == MAT_INITIAL_MATRIX) {
9864     mloc_sub = PETSC_DECIDE;
9865     nloc_sub = PETSC_DECIDE;
9866     if (bs < 1) {
9867       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
9868       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
9869     } else {
9870       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
9871       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
9872     }
9873     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
9874     rstart = rend - mloc_sub;
9875     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
9876     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
9877   } else { /* reuse == MAT_REUSE_MATRIX */
9878     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");
9879     /* retrieve subcomm */
9880     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
9881     redund = (*matredundant)->redundant;
9882     isrow  = redund->isrow;
9883     iscol  = redund->iscol;
9884     matseq = redund->matseq;
9885   }
9886   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
9887 
9888   /* get matredundant over subcomm */
9889   if (reuse == MAT_INITIAL_MATRIX) {
9890     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
9891 
9892     /* create a supporting struct and attach it to C for reuse */
9893     PetscCall(PetscNewLog(*matredundant, &redund));
9894     (*matredundant)->redundant = redund;
9895     redund->isrow              = isrow;
9896     redund->iscol              = iscol;
9897     redund->matseq             = matseq;
9898     if (newsubcomm) {
9899       redund->subcomm = subcomm;
9900     } else {
9901       redund->subcomm = MPI_COMM_NULL;
9902     }
9903   } else {
9904     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
9905   }
9906 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
9907   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
9908     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
9909     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
9910   }
9911 #endif
9912   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
9913   PetscFunctionReturn(0);
9914 }
9915 
9916 /*@C
9917    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
9918    a given `Mat`. Each submatrix can span multiple procs.
9919 
9920    Collective on mat
9921 
9922    Input Parameters:
9923 +  mat - the matrix
9924 .  subcomm - the subcommunicator obtained by MPI_Com_split(comm)
9925 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9926 
9927    Output Parameter:
9928 .  subMat - 'parallel submatrices each spans a given subcomm
9929 
9930   Notes:
9931   The submatrix partition across processors is dictated by 'subComm' a
9932   communicator obtained by MPI_comm_split() or via `PetscSubcommCreate()`. The subComm
9933   is not restriced to be grouped with consecutive original ranks.
9934 
9935   Due the MPI_Comm_split() usage, the parallel layout of the submatrices
9936   map directly to the layout of the original matrix [wrt the local
9937   row,col partitioning]. So the original 'DiagonalMat' naturally maps
9938   into the 'DiagonalMat' of the subMat, hence it is used directly from
9939   the subMat. However the offDiagMat looses some columns - and this is
9940   reconstructed with `MatSetValues()`
9941 
9942   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
9943 
9944   Level: advanced
9945 
9946 .seealso: `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
9947 @*/
9948 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat) {
9949   PetscMPIInt commsize, subCommSize;
9950 
9951   PetscFunctionBegin;
9952   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
9953   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
9954   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
9955 
9956   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");
9957   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
9958   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
9959   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
9960   PetscFunctionReturn(0);
9961 }
9962 
9963 /*@
9964    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
9965 
9966    Not Collective
9967 
9968    Input Parameters:
9969 +  mat - matrix to extract local submatrix from
9970 .  isrow - local row indices for submatrix
9971 -  iscol - local column indices for submatrix
9972 
9973    Output Parameter:
9974 .  submat - the submatrix
9975 
9976    Level: intermediate
9977 
9978    Notes:
9979    The submat should be returned with `MatRestoreLocalSubMatrix()`.
9980 
9981    Depending on the format of mat, the returned submat may not implement `MatMult()`.  Its communicator may be
9982    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of mat's.
9983 
9984    The submat always implements `MatSetValuesLocal()`.  If isrow and iscol have the same block size, then
9985    `MatSetValuesBlockedLocal()` will also be implemented.
9986 
9987    The mat must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
9988    Matrices obtained with DMCreateMatrix() generally already have the local to global mapping provided.
9989 
9990 .seealso: `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
9991 @*/
9992 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) {
9993   PetscFunctionBegin;
9994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9995   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
9996   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
9997   PetscCheckSameComm(isrow, 2, iscol, 3);
9998   PetscValidPointer(submat, 4);
9999   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10000 
10001   if (mat->ops->getlocalsubmatrix) {
10002     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10003   } else {
10004     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10005   }
10006   PetscFunctionReturn(0);
10007 }
10008 
10009 /*@
10010    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10011 
10012    Not Collective
10013 
10014    Input Parameters:
10015 +  mat - matrix to extract local submatrix from
10016 .  isrow - local row indices for submatrix
10017 .  iscol - local column indices for submatrix
10018 -  submat - the submatrix
10019 
10020    Level: intermediate
10021 
10022 .seealso: `MatGetLocalSubMatrix()`
10023 @*/
10024 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat) {
10025   PetscFunctionBegin;
10026   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10027   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10028   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10029   PetscCheckSameComm(isrow, 2, iscol, 3);
10030   PetscValidPointer(submat, 4);
10031   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10032 
10033   if (mat->ops->restorelocalsubmatrix) {
10034     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10035   } else {
10036     PetscCall(MatDestroy(submat));
10037   }
10038   *submat = NULL;
10039   PetscFunctionReturn(0);
10040 }
10041 
10042 /* --------------------------------------------------------*/
10043 /*@
10044    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10045 
10046    Collective on mat
10047 
10048    Input Parameter:
10049 .  mat - the matrix
10050 
10051    Output Parameter:
10052 .  is - if any rows have zero diagonals this contains the list of them
10053 
10054    Level: developer
10055 
10056 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10057 @*/
10058 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is) {
10059   PetscFunctionBegin;
10060   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10061   PetscValidType(mat, 1);
10062   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10063   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10064 
10065   if (!mat->ops->findzerodiagonals) {
10066     Vec                diag;
10067     const PetscScalar *a;
10068     PetscInt          *rows;
10069     PetscInt           rStart, rEnd, r, nrow = 0;
10070 
10071     PetscCall(MatCreateVecs(mat, &diag, NULL));
10072     PetscCall(MatGetDiagonal(mat, diag));
10073     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10074     PetscCall(VecGetArrayRead(diag, &a));
10075     for (r = 0; r < rEnd - rStart; ++r)
10076       if (a[r] == 0.0) ++nrow;
10077     PetscCall(PetscMalloc1(nrow, &rows));
10078     nrow = 0;
10079     for (r = 0; r < rEnd - rStart; ++r)
10080       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10081     PetscCall(VecRestoreArrayRead(diag, &a));
10082     PetscCall(VecDestroy(&diag));
10083     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10084   } else {
10085     PetscUseTypeMethod(mat, findzerodiagonals, is);
10086   }
10087   PetscFunctionReturn(0);
10088 }
10089 
10090 /*@
10091    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10092 
10093    Collective on mat
10094 
10095    Input Parameter:
10096 .  mat - the matrix
10097 
10098    Output Parameter:
10099 .  is - contains the list of rows with off block diagonal entries
10100 
10101    Level: developer
10102 
10103 .seealso: `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10104 @*/
10105 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is) {
10106   PetscFunctionBegin;
10107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10108   PetscValidType(mat, 1);
10109   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10110   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10111 
10112   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10113   PetscFunctionReturn(0);
10114 }
10115 
10116 /*@C
10117   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10118 
10119   Collective on mat
10120 
10121   Input Parameters:
10122 . mat - the matrix
10123 
10124   Output Parameters:
10125 . values - the block inverses in column major order (FORTRAN-like)
10126 
10127    Notes:
10128    The size of the blocks is determined by the block size of the matrix.
10129 
10130    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10131 
10132    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10133 
10134    Fortran Note:
10135      This routine is not available from Fortran.
10136 
10137   Level: advanced
10138 
10139 .seealso: `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10140 @*/
10141 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values) {
10142   PetscFunctionBegin;
10143   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10144   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10145   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10146   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10147   PetscFunctionReturn(0);
10148 }
10149 
10150 /*@C
10151   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10152 
10153   Collective on mat
10154 
10155   Input Parameters:
10156 + mat - the matrix
10157 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10158 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10159 
10160   Output Parameters:
10161 . values - the block inverses in column major order (FORTRAN-like)
10162 
10163   Notes:
10164   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10165 
10166   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10167 
10168   Fortran Note:
10169   This routine is not available from Fortran.
10170 
10171   Level: advanced
10172 
10173 .seealso: `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10174 @*/
10175 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values) {
10176   PetscFunctionBegin;
10177   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10178   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10179   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10180   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10181   PetscFunctionReturn(0);
10182 }
10183 
10184 /*@
10185   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10186 
10187   Collective on Mat
10188 
10189   Input Parameters:
10190 + A - the matrix
10191 - C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
10192 
10193   Note:
10194   The blocksize of the matrix is used to determine the blocks on the diagonal of C
10195 
10196   Level: advanced
10197 
10198 .seealso: `MatInvertBlockDiagonal()`
10199 @*/
10200 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C) {
10201   const PetscScalar *vals;
10202   PetscInt          *dnnz;
10203   PetscInt           m, rstart, rend, bs, i, j;
10204 
10205   PetscFunctionBegin;
10206   PetscCall(MatInvertBlockDiagonal(A, &vals));
10207   PetscCall(MatGetBlockSize(A, &bs));
10208   PetscCall(MatGetLocalSize(A, &m, NULL));
10209   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10210   PetscCall(PetscMalloc1(m / bs, &dnnz));
10211   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10212   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10213   PetscCall(PetscFree(dnnz));
10214   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10215   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10216   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10217   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10218   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10219   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10220   PetscFunctionReturn(0);
10221 }
10222 
10223 /*@C
10224     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10225     via `MatTransposeColoringCreate()`.
10226 
10227     Collective on c
10228 
10229     Input Parameter:
10230 .   c - coloring context
10231 
10232     Level: intermediate
10233 
10234 .seealso: `MatTransposeColoringCreate()`
10235 @*/
10236 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c) {
10237   MatTransposeColoring matcolor = *c;
10238 
10239   PetscFunctionBegin;
10240   if (!matcolor) PetscFunctionReturn(0);
10241   if (--((PetscObject)matcolor)->refct > 0) {
10242     matcolor = NULL;
10243     PetscFunctionReturn(0);
10244   }
10245 
10246   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10247   PetscCall(PetscFree(matcolor->rows));
10248   PetscCall(PetscFree(matcolor->den2sp));
10249   PetscCall(PetscFree(matcolor->colorforcol));
10250   PetscCall(PetscFree(matcolor->columns));
10251   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10252   PetscCall(PetscHeaderDestroy(c));
10253   PetscFunctionReturn(0);
10254 }
10255 
10256 /*@C
10257     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10258     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10259     `MatTransposeColoring` to sparse B.
10260 
10261     Collective on coloring
10262 
10263     Input Parameters:
10264 +   B - sparse matrix B
10265 .   Btdense - symbolic dense matrix B^T
10266 -   coloring - coloring context created with `MatTransposeColoringCreate()`
10267 
10268     Output Parameter:
10269 .   Btdense - dense matrix B^T
10270 
10271     Level: developer
10272 
10273     Note:
10274     These are used internally for some implementations of `MatRARt()`
10275 
10276 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10277 
10278 @*/
10279 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense) {
10280   PetscFunctionBegin;
10281   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10282   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10283   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10284 
10285   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10286   PetscFunctionReturn(0);
10287 }
10288 
10289 /*@C
10290     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10291     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10292     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10293     Csp from Cden.
10294 
10295     Collective on matcoloring
10296 
10297     Input Parameters:
10298 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10299 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10300 
10301     Output Parameter:
10302 .   Csp - sparse matrix
10303 
10304     Level: developer
10305 
10306     Note:
10307     These are used internally for some implementations of `MatRARt()`
10308 
10309 .seealso: `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10310 
10311 @*/
10312 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp) {
10313   PetscFunctionBegin;
10314   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10315   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10316   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10317 
10318   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10319   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10320   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10321   PetscFunctionReturn(0);
10322 }
10323 
10324 /*@C
10325    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10326 
10327    Collective on mat
10328 
10329    Input Parameters:
10330 +  mat - the matrix product C
10331 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10332 
10333     Output Parameter:
10334 .   color - the new coloring context
10335 
10336     Level: intermediate
10337 
10338 .seealso: `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10339           `MatTransColoringApplyDenToSp()`
10340 @*/
10341 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color) {
10342   MatTransposeColoring c;
10343   MPI_Comm             comm;
10344 
10345   PetscFunctionBegin;
10346   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10347   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10348   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10349 
10350   c->ctype = iscoloring->ctype;
10351   if (mat->ops->transposecoloringcreate) {
10352     PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10353   } else SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Code not yet written for matrix type %s", ((PetscObject)mat)->type_name);
10354 
10355   *color = c;
10356   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10357   PetscFunctionReturn(0);
10358 }
10359 
10360 /*@
10361       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10362         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10363         same, otherwise it will be larger
10364 
10365      Not Collective
10366 
10367   Input Parameter:
10368 .    A  - the matrix
10369 
10370   Output Parameter:
10371 .    state - the current state
10372 
10373   Notes:
10374     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10375          different matrices
10376 
10377     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10378 
10379     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10380 
10381   Level: intermediate
10382 
10383 .seealso: `PetscObjectStateGet()`, `PetscObjectGetId()`
10384 @*/
10385 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state) {
10386   PetscFunctionBegin;
10387   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10388   *state = mat->nonzerostate;
10389   PetscFunctionReturn(0);
10390 }
10391 
10392 /*@
10393       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10394                  matrices from each processor
10395 
10396     Collective
10397 
10398    Input Parameters:
10399 +    comm - the communicators the parallel matrix will live on
10400 .    seqmat - the input sequential matrices
10401 .    n - number of local columns (or `PETSC_DECIDE`)
10402 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10403 
10404    Output Parameter:
10405 .    mpimat - the parallel matrix generated
10406 
10407     Level: developer
10408 
10409    Note:
10410     The number of columns of the matrix in EACH processor MUST be the same.
10411 
10412 .seealso: `Mat`
10413 @*/
10414 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat) {
10415   PetscMPIInt size;
10416 
10417   PetscFunctionBegin;
10418   PetscCallMPI(MPI_Comm_size(comm, &size));
10419   if (size == 1) {
10420     if (reuse == MAT_INITIAL_MATRIX) {
10421       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10422     } else {
10423       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10424     }
10425     PetscFunctionReturn(0);
10426   }
10427 
10428   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");
10429 
10430   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10431   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10432   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10433   PetscFunctionReturn(0);
10434 }
10435 
10436 /*@
10437      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10438 
10439     Collective on A
10440 
10441    Input Parameters:
10442 +    A   - the matrix to create subdomains from
10443 -    N   - requested number of subdomains
10444 
10445    Output Parameters:
10446 +    n   - number of subdomains resulting on this rank
10447 -    iss - `IS` list with indices of subdomains on this rank
10448 
10449     Level: advanced
10450 
10451     Note:
10452     The number of subdomains must be smaller than the communicator size
10453 
10454 .seealso: `Mat`, `IS`
10455 @*/
10456 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[]) {
10457   MPI_Comm    comm, subcomm;
10458   PetscMPIInt size, rank, color;
10459   PetscInt    rstart, rend, k;
10460 
10461   PetscFunctionBegin;
10462   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10463   PetscCallMPI(MPI_Comm_size(comm, &size));
10464   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10465   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);
10466   *n    = 1;
10467   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10468   color = rank / k;
10469   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10470   PetscCall(PetscMalloc1(1, iss));
10471   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10472   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10473   PetscCallMPI(MPI_Comm_free(&subcomm));
10474   PetscFunctionReturn(0);
10475 }
10476 
10477 /*@
10478    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10479 
10480    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10481    If they are not the same, uses `MatMatMatMult()`.
10482 
10483    Once the coarse grid problem is constructed, correct for interpolation operators
10484    that are not of full rank, which can legitimately happen in the case of non-nested
10485    geometric multigrid.
10486 
10487    Input Parameters:
10488 +  restrct - restriction operator
10489 .  dA - fine grid matrix
10490 .  interpolate - interpolation operator
10491 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10492 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10493 
10494    Output Parameters:
10495 .  A - the Galerkin coarse matrix
10496 
10497    Options Database Key:
10498 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10499 
10500    Level: developer
10501 
10502 .seealso: `MatPtAP()`, `MatMatMatMult()`
10503 @*/
10504 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A) {
10505   IS  zerorows;
10506   Vec diag;
10507 
10508   PetscFunctionBegin;
10509   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10510   /* Construct the coarse grid matrix */
10511   if (interpolate == restrct) {
10512     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10513   } else {
10514     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10515   }
10516 
10517   /* If the interpolation matrix is not of full rank, A will have zero rows.
10518      This can legitimately happen in the case of non-nested geometric multigrid.
10519      In that event, we set the rows of the matrix to the rows of the identity,
10520      ignoring the equations (as the RHS will also be zero). */
10521 
10522   PetscCall(MatFindZeroRows(*A, &zerorows));
10523 
10524   if (zerorows != NULL) { /* if there are any zero rows */
10525     PetscCall(MatCreateVecs(*A, &diag, NULL));
10526     PetscCall(MatGetDiagonal(*A, diag));
10527     PetscCall(VecISSet(diag, zerorows, 1.0));
10528     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10529     PetscCall(VecDestroy(&diag));
10530     PetscCall(ISDestroy(&zerorows));
10531   }
10532   PetscFunctionReturn(0);
10533 }
10534 
10535 /*@C
10536     MatSetOperation - Allows user to set a matrix operation for any matrix type
10537 
10538    Logically Collective on mat
10539 
10540     Input Parameters:
10541 +   mat - the matrix
10542 .   op - the name of the operation
10543 -   f - the function that provides the operation
10544 
10545    Level: developer
10546 
10547     Usage:
10548 $      extern PetscErrorCode usermult(Mat,Vec,Vec);
10549 $      PetscCall(MatCreateXXX(comm,...&A);
10550 $      PetscCall(MatSetOperation(A,MATOP_MULT,(void(*)(void))usermult);
10551 
10552     Notes:
10553     See the file include/petscmat.h for a complete list of matrix
10554     operations, which all have the form MATOP_<OPERATION>, where
10555     <OPERATION> is the name (in all capital letters) of the
10556     user interface routine (e.g., MatMult() -> MATOP_MULT).
10557 
10558     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10559     sequence as the usual matrix interface routines, since they
10560     are intended to be accessed via the usual matrix interface
10561     routines, e.g.,
10562 $       MatMult(Mat,Vec,Vec) -> usermult(Mat,Vec,Vec)
10563 
10564     In particular each function MUST return an error code of 0 on success and
10565     nonzero on failure.
10566 
10567     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10568 
10569 .seealso: `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10570 @*/
10571 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void)) {
10572   PetscFunctionBegin;
10573   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10574   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10575   (((void (**)(void))mat->ops)[op]) = f;
10576   PetscFunctionReturn(0);
10577 }
10578 
10579 /*@C
10580     MatGetOperation - Gets a matrix operation for any matrix type.
10581 
10582     Not Collective
10583 
10584     Input Parameters:
10585 +   mat - the matrix
10586 -   op - the name of the operation
10587 
10588     Output Parameter:
10589 .   f - the function that provides the operation
10590 
10591     Level: developer
10592 
10593     Usage:
10594 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
10595 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
10596 
10597     Notes:
10598     See the file include/petscmat.h for a complete list of matrix
10599     operations, which all have the form MATOP_<OPERATION>, where
10600     <OPERATION> is the name (in all capital letters) of the
10601     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10602 
10603     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
10604 
10605 .seealso: `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
10606 @*/
10607 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void)) {
10608   PetscFunctionBegin;
10609   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10610   *f = (((void (**)(void))mat->ops)[op]);
10611   PetscFunctionReturn(0);
10612 }
10613 
10614 /*@
10615     MatHasOperation - Determines whether the given matrix supports the particular operation.
10616 
10617    Not Collective
10618 
10619    Input Parameters:
10620 +  mat - the matrix
10621 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
10622 
10623    Output Parameter:
10624 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
10625 
10626    Level: advanced
10627 
10628    Note:
10629    See the file include/petscmat.h for a complete list of matrix
10630    operations, which all have the form MATOP_<OPERATION>, where
10631    <OPERATION> is the name (in all capital letters) of the
10632    user-level routine.  E.g., `MatNorm()` -> `MATOP_NORM`.
10633 
10634 .seealso: `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
10635 @*/
10636 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has) {
10637   PetscFunctionBegin;
10638   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10639   PetscValidBoolPointer(has, 3);
10640   if (mat->ops->hasoperation) {
10641     PetscUseTypeMethod(mat, hasoperation, op, has);
10642   } else {
10643     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
10644     else {
10645       *has = PETSC_FALSE;
10646       if (op == MATOP_CREATE_SUBMATRIX) {
10647         PetscMPIInt size;
10648 
10649         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10650         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
10651       }
10652     }
10653   }
10654   PetscFunctionReturn(0);
10655 }
10656 
10657 /*@
10658     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
10659 
10660    Collective on mat
10661 
10662    Input Parameters:
10663 .  mat - the matrix
10664 
10665    Output Parameter:
10666 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
10667 
10668    Level: beginner
10669 
10670 .seealso: `MatCreate()`, `MatSetSizes()`, `PetscLayout`
10671 @*/
10672 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong) {
10673   PetscFunctionBegin;
10674   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10675   PetscValidType(mat, 1);
10676   PetscValidBoolPointer(cong, 2);
10677   if (!mat->rmap || !mat->cmap) {
10678     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
10679     PetscFunctionReturn(0);
10680   }
10681   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
10682     PetscCall(PetscLayoutSetUp(mat->rmap));
10683     PetscCall(PetscLayoutSetUp(mat->cmap));
10684     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
10685     if (*cong) mat->congruentlayouts = 1;
10686     else mat->congruentlayouts = 0;
10687   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
10688   PetscFunctionReturn(0);
10689 }
10690 
10691 PetscErrorCode MatSetInf(Mat A) {
10692   PetscFunctionBegin;
10693   PetscUseTypeMethod(A, setinf);
10694   PetscFunctionReturn(0);
10695 }
10696 
10697 /*C
10698    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
10699 
10700    Collective on mat
10701 
10702    Input Parameters:
10703 +  A - the matrix
10704 -  sym - `PETSC_TRUE` indicates that the graph will be symmetrized
10705 .  scale - `PETSC_TRUE` indicates that the graph will be scaled with the diagonal
10706 
10707    Output Parameter:
10708 .  graph - the resulting graph
10709 
10710    Level: advanced
10711 
10712 .seealso: `MatCreate()`, `MatFilter()`
10713 */
10714 PETSC_EXTERN PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, Mat *graph) {
10715   PetscFunctionBegin;
10716   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
10717   PetscValidType(A, 1);
10718   PetscValidPointer(graph, 3);
10719   PetscUseTypeMethod(A, creategraph, sym, scale, graph);
10720   PetscFunctionReturn(0);
10721 }
10722 
10723 /*C
10724    MatFilter - filters a matrices values with an absolut value equal to or below a give threshold
10725 
10726    Collective on mat
10727 
10728    Input Parameter:
10729 .  value - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries <= value
10730 
10731    Input/Output Parameter:
10732 .  A - the `Mat` to filter in place
10733 
10734    Level: developer
10735 
10736    Note:
10737    This is called before graph coarsers are called in `PCGAMG`
10738 
10739 .seealso: `MatCreate()`, `MatCreateGraph()`
10740 */
10741 PETSC_EXTERN PetscErrorCode MatFilter(Mat G, PetscReal value, Mat *F) {
10742   PetscFunctionBegin;
10743   PetscValidHeaderSpecific(G, MAT_CLASSID, 1);
10744   PetscValidType(G, 1);
10745   PetscValidPointer(F, 3);
10746   if (value >= 0.0) PetscCall((G->ops->filter)(G, value, F));
10747   PetscFunctionReturn(0);
10748 }
10749