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