xref: /petsc/src/mat/interface/matrix.c (revision 7c561f0977de51325d9fcc8e06f17306dbb264cc)
1 /*
2    This is where the abstract matrix operations are defined
3    Portions of this code are under:
4    Copyright (c) 2022 Advanced Micro Devices, Inc. All rights reserved.
5 */
6 
7 #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/
8 #include <petsc/private/isimpl.h>
9 #include <petsc/private/vecimpl.h>
10 
11 /* Logging support */
12 PetscClassId MAT_CLASSID;
13 PetscClassId MAT_COLORING_CLASSID;
14 PetscClassId MAT_FDCOLORING_CLASSID;
15 PetscClassId MAT_TRANSPOSECOLORING_CLASSID;
16 
17 PetscLogEvent MAT_Mult, MAT_Mults, MAT_MultAdd, MAT_MultTranspose;
18 PetscLogEvent MAT_MultTransposeAdd, MAT_Solve, MAT_Solves, MAT_SolveAdd, MAT_SolveTranspose, MAT_MatSolve, MAT_MatTrSolve;
19 PetscLogEvent MAT_SolveTransposeAdd, MAT_SOR, MAT_ForwardSolve, MAT_BackwardSolve, MAT_LUFactor, MAT_LUFactorSymbolic;
20 PetscLogEvent MAT_LUFactorNumeric, MAT_CholeskyFactor, MAT_CholeskyFactorSymbolic, MAT_CholeskyFactorNumeric, MAT_ILUFactor;
21 PetscLogEvent MAT_ILUFactorSymbolic, MAT_ICCFactorSymbolic, MAT_Copy, MAT_Convert, MAT_Scale, MAT_AssemblyBegin;
22 PetscLogEvent MAT_QRFactorNumeric, MAT_QRFactorSymbolic, MAT_QRFactor;
23 PetscLogEvent MAT_AssemblyEnd, MAT_SetValues, MAT_GetValues, MAT_GetRow, MAT_GetRowIJ, MAT_CreateSubMats, MAT_GetOrdering, MAT_RedundantMat, MAT_GetSeqNonzeroStructure;
24 PetscLogEvent MAT_IncreaseOverlap, MAT_Partitioning, MAT_PartitioningND, MAT_Coarsen, MAT_ZeroEntries, MAT_Load, MAT_View, MAT_AXPY, MAT_FDColoringCreate;
25 PetscLogEvent MAT_FDColoringSetUp, MAT_FDColoringApply, MAT_Transpose, MAT_FDColoringFunction, MAT_CreateSubMat;
26 PetscLogEvent MAT_TransposeColoringCreate;
27 PetscLogEvent MAT_MatMult, MAT_MatMultSymbolic, MAT_MatMultNumeric;
28 PetscLogEvent MAT_PtAP, MAT_PtAPSymbolic, MAT_PtAPNumeric, MAT_RARt, MAT_RARtSymbolic, MAT_RARtNumeric;
29 PetscLogEvent MAT_MatTransposeMult, MAT_MatTransposeMultSymbolic, MAT_MatTransposeMultNumeric;
30 PetscLogEvent MAT_TransposeMatMult, MAT_TransposeMatMultSymbolic, MAT_TransposeMatMultNumeric;
31 PetscLogEvent MAT_MatMatMult, MAT_MatMatMultSymbolic, MAT_MatMatMultNumeric;
32 PetscLogEvent MAT_MultHermitianTranspose, MAT_MultHermitianTransposeAdd;
33 PetscLogEvent MAT_Getsymtranspose, MAT_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_Applypapt, MAT_Applypapt_numeric, MAT_Applypapt_symbolic, MAT_GetSequentialNonzeroStructure;
36 PetscLogEvent MAT_GetMultiProcBlock;
37 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
38 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
39 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
40 PetscLogEvent MAT_SetValuesBatch;
41 PetscLogEvent MAT_ViennaCLCopyToGPU;
42 PetscLogEvent MAT_DenseCopyToGPU, MAT_DenseCopyFromGPU;
43 PetscLogEvent MAT_Merge, MAT_Residual, MAT_SetRandom;
44 PetscLogEvent MAT_FactorFactS, MAT_FactorInvS;
45 PetscLogEvent MATCOLORING_Apply, MATCOLORING_Comm, MATCOLORING_Local, MATCOLORING_ISCreate, MATCOLORING_SetUp, MATCOLORING_Weights;
46 PetscLogEvent MAT_H2Opus_Build, MAT_H2Opus_Compress, MAT_H2Opus_Orthog, MAT_H2Opus_LR;
47 
48 const char *const MatFactorTypes[] = {"NONE", "LU", "CHOLESKY", "ILU", "ICC", "ILUDT", "QR", "MatFactorType", "MAT_FACTOR_", NULL};
49 
50 /*@
51    MatSetRandom - Sets all components of a matrix to random numbers.
52 
53    Logically Collective
54 
55    Input Parameters:
56 +  x  - the matrix
57 -  rctx - the `PetscRandom` object, formed by `PetscRandomCreate()`, or `NULL` and
58           it will create one internally.
59 
60    Output Parameter:
61 .  x  - the matrix
62 
63    Example:
64 .vb
65      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
66      MatSetRandom(x,rctx);
67      PetscRandomDestroy(rctx);
68 .ve
69 
70    Level: intermediate
71 
72    Note:
73    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
74    for sparse matrices that already have locations it fills the locations with random numbers. It generates an error if used on sparse matrices that have
75    not been preallocated.
76 
77 .seealso: `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
78 @*/
79 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
80 {
81   PetscRandom randObj = NULL;
82 
83   PetscFunctionBegin;
84   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
85   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
86   PetscValidType(x, 1);
87   MatCheckPreallocated(x, 1);
88 
89   if (!rctx) {
90     MPI_Comm comm;
91     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
92     PetscCall(PetscRandomCreate(comm, &randObj));
93     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
94     PetscCall(PetscRandomSetFromOptions(randObj));
95     rctx = randObj;
96   }
97   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
98   PetscUseTypeMethod(x, setrandom, rctx);
99   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
100 
101   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
103   PetscCall(PetscRandomDestroy(&randObj));
104   PetscFunctionReturn(PETSC_SUCCESS);
105 }
106 
107 /*@
108    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
109 
110    Logically Collective
111 
112    Input Parameter:
113 .  mat - the factored matrix
114 
115    Output Parameters:
116 +  pivot - the pivot value computed
117 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
118          the share the matrix
119 
120    Level: advanced
121 
122    Notes:
123     This routine does not work for factorizations done with external packages.
124 
125     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
126 
127     This can be called on non-factored matrices that come from, for example, matrices used in SOR.
128 
129 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
130           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
131 @*/
132 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
133 {
134   PetscFunctionBegin;
135   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
136   PetscValidRealPointer(pivot, 2);
137   PetscValidIntPointer(row, 3);
138   *pivot = mat->factorerror_zeropivot_value;
139   *row   = mat->factorerror_zeropivot_row;
140   PetscFunctionReturn(PETSC_SUCCESS);
141 }
142 
143 /*@
144    MatFactorGetError - gets the error code from a factorization
145 
146    Logically Collective
147 
148    Input Parameters:
149 .  mat - the factored matrix
150 
151    Output Parameter:
152 .  err  - the error code
153 
154    Level: advanced
155 
156    Note:
157     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
158 
159 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
160           `MatFactorError`
161 @*/
162 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
163 {
164   PetscFunctionBegin;
165   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
166   PetscValidPointer(err, 2);
167   *err = mat->factorerrortype;
168   PetscFunctionReturn(PETSC_SUCCESS);
169 }
170 
171 /*@
172    MatFactorClearError - clears the error code in a factorization
173 
174    Logically Collective
175 
176    Input Parameter:
177 .  mat - the factored matrix
178 
179    Level: developer
180 
181    Note:
182     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
183 
184 .seealso: `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
185           `MatGetErrorCode()`, `MatFactorError`
186 @*/
187 PetscErrorCode MatFactorClearError(Mat mat)
188 {
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
191   mat->factorerrortype             = MAT_FACTOR_NOERROR;
192   mat->factorerror_zeropivot_value = 0.0;
193   mat->factorerror_zeropivot_row   = 0;
194   PetscFunctionReturn(PETSC_SUCCESS);
195 }
196 
197 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
198 {
199   Vec                r, l;
200   const PetscScalar *al;
201   PetscInt           i, nz, gnz, N, n;
202 
203   PetscFunctionBegin;
204   PetscCall(MatCreateVecs(mat, &r, &l));
205   if (!cols) { /* nonzero rows */
206     PetscCall(MatGetSize(mat, &N, NULL));
207     PetscCall(MatGetLocalSize(mat, &n, NULL));
208     PetscCall(VecSet(l, 0.0));
209     PetscCall(VecSetRandom(r, NULL));
210     PetscCall(MatMult(mat, r, l));
211     PetscCall(VecGetArrayRead(l, &al));
212   } else { /* nonzero columns */
213     PetscCall(MatGetSize(mat, NULL, &N));
214     PetscCall(MatGetLocalSize(mat, NULL, &n));
215     PetscCall(VecSet(r, 0.0));
216     PetscCall(VecSetRandom(l, NULL));
217     PetscCall(MatMultTranspose(mat, l, r));
218     PetscCall(VecGetArrayRead(r, &al));
219   }
220   if (tol <= 0.0) {
221     for (i = 0, nz = 0; i < n; i++)
222       if (al[i] != 0.0) nz++;
223   } else {
224     for (i = 0, nz = 0; i < n; i++)
225       if (PetscAbsScalar(al[i]) > tol) nz++;
226   }
227   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
228   if (gnz != N) {
229     PetscInt *nzr;
230     PetscCall(PetscMalloc1(nz, &nzr));
231     if (nz) {
232       if (tol < 0) {
233         for (i = 0, nz = 0; i < n; i++)
234           if (al[i] != 0.0) nzr[nz++] = i;
235       } else {
236         for (i = 0, nz = 0; i < n; i++)
237           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
238       }
239     }
240     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
241   } else *nonzero = NULL;
242   if (!cols) { /* nonzero rows */
243     PetscCall(VecRestoreArrayRead(l, &al));
244   } else {
245     PetscCall(VecRestoreArrayRead(r, &al));
246   }
247   PetscCall(VecDestroy(&l));
248   PetscCall(VecDestroy(&r));
249   PetscFunctionReturn(PETSC_SUCCESS);
250 }
251 
252 /*@
253       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
254 
255   Input Parameter:
256 .    A  - the matrix
257 
258   Output Parameter:
259 .    keptrows - the rows that are not completely zero
260 
261   Level: intermediate
262 
263   Note:
264     `keptrows` is set to `NULL` if all rows are nonzero.
265 
266 .seealso: `Mat`, `MatFindZeroRows()`
267  @*/
268 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
269 {
270   PetscFunctionBegin;
271   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
272   PetscValidType(mat, 1);
273   PetscValidPointer(keptrows, 2);
274   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
275   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
276   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
277   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
278   PetscFunctionReturn(PETSC_SUCCESS);
279 }
280 
281 /*@
282       MatFindZeroRows - Locate all rows that are completely zero in the matrix
283 
284   Input Parameter:
285 .    A  - the matrix
286 
287   Output Parameter:
288 .    zerorows - the rows that are completely zero
289 
290   Level: intermediate
291 
292   Note:
293     `zerorows` is set to `NULL` if no rows are zero.
294 
295 .seealso: `Mat`, `MatFindNonzeroRows()`
296  @*/
297 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
298 {
299   IS       keptrows;
300   PetscInt m, n;
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
304   PetscValidType(mat, 1);
305   PetscValidPointer(zerorows, 2);
306   PetscCall(MatFindNonzeroRows(mat, &keptrows));
307   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
308      In keeping with this convention, we set zerorows to NULL if there are no zero
309      rows. */
310   if (keptrows == NULL) {
311     *zerorows = NULL;
312   } else {
313     PetscCall(MatGetOwnershipRange(mat, &m, &n));
314     PetscCall(ISComplement(keptrows, m, n, zerorows));
315     PetscCall(ISDestroy(&keptrows));
316   }
317   PetscFunctionReturn(PETSC_SUCCESS);
318 }
319 
320 /*@
321    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
322 
323    Not Collective
324 
325    Input Parameters:
326 .   A - the matrix
327 
328    Output Parameters:
329 .   a - the diagonal part (which is a SEQUENTIAL matrix)
330 
331    Level: advanced
332 
333    Notes:
334    See the manual page for `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
335 
336    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
337 
338 .seealso: `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
339 @*/
340 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
341 {
342   PetscFunctionBegin;
343   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
344   PetscValidType(A, 1);
345   PetscValidPointer(a, 2);
346   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
347   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
348   else {
349     PetscMPIInt size;
350 
351     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
352     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
353     *a = A;
354   }
355   PetscFunctionReturn(PETSC_SUCCESS);
356 }
357 
358 /*@
359    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
360 
361    Collective
362 
363    Input Parameters:
364 .  mat - the matrix
365 
366    Output Parameter:
367 .   trace - the sum of the diagonal entries
368 
369    Level: advanced
370 
371 .seealso: `Mat`
372 @*/
373 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
374 {
375   Vec diag;
376 
377   PetscFunctionBegin;
378   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
379   PetscValidScalarPointer(trace, 2);
380   PetscCall(MatCreateVecs(mat, &diag, NULL));
381   PetscCall(MatGetDiagonal(mat, diag));
382   PetscCall(VecSum(diag, trace));
383   PetscCall(VecDestroy(&diag));
384   PetscFunctionReturn(PETSC_SUCCESS);
385 }
386 
387 /*@
388    MatRealPart - Zeros out the imaginary part of the matrix
389 
390    Logically Collective
391 
392    Input Parameters:
393 .  mat - the matrix
394 
395    Level: advanced
396 
397 .seealso: `Mat`, `MatImaginaryPart()`
398 @*/
399 PetscErrorCode MatRealPart(Mat mat)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
403   PetscValidType(mat, 1);
404   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
405   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
406   MatCheckPreallocated(mat, 1);
407   PetscUseTypeMethod(mat, realpart);
408   PetscFunctionReturn(PETSC_SUCCESS);
409 }
410 
411 /*@C
412    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
413 
414    Collective
415 
416    Input Parameter:
417 .  mat - the matrix
418 
419    Output Parameters:
420 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
421 -   ghosts - the global indices of the ghost points
422 
423    Level: advanced
424 
425    Note:
426    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
427 
428 .seealso: `Mat`, `VecCreateGhost()`
429 @*/
430 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
431 {
432   PetscFunctionBegin;
433   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
434   PetscValidType(mat, 1);
435   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
436   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
437   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
438   else {
439     if (nghosts) *nghosts = 0;
440     if (ghosts) *ghosts = NULL;
441   }
442   PetscFunctionReturn(PETSC_SUCCESS);
443 }
444 
445 /*@
446    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
447 
448    Logically Collective
449 
450    Input Parameters:
451 .  mat - the matrix
452 
453    Level: advanced
454 
455 .seealso: `Mat`, `MatRealPart()`
456 @*/
457 PetscErrorCode MatImaginaryPart(Mat mat)
458 {
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
461   PetscValidType(mat, 1);
462   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
463   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
464   MatCheckPreallocated(mat, 1);
465   PetscUseTypeMethod(mat, imaginarypart);
466   PetscFunctionReturn(PETSC_SUCCESS);
467 }
468 
469 /*@
470    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
471 
472    Not Collective
473 
474    Input Parameter:
475 .  mat - the matrix
476 
477    Output Parameters:
478 +  missing - is any diagonal missing
479 -  dd - first diagonal entry that is missing (optional) on this process
480 
481    Level: advanced
482 
483 .seealso: `Mat`
484 @*/
485 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
486 {
487   PetscFunctionBegin;
488   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
489   PetscValidType(mat, 1);
490   PetscValidBoolPointer(missing, 2);
491   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
492   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
493   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
494   PetscFunctionReturn(PETSC_SUCCESS);
495 }
496 
497 /*@C
498    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
499    for each row that you get to ensure that your application does
500    not bleed memory.
501 
502    Not Collective
503 
504    Input Parameters:
505 +  mat - the matrix
506 -  row - the row to get
507 
508    Output Parameters:
509 +  ncols -  if not `NULL`, the number of nonzeros in the row
510 .  cols - if not `NULL`, the column numbers
511 -  vals - if not `NULL`, the values
512 
513    Level: advanced
514 
515    Notes:
516    This routine is provided for people who need to have direct access
517    to the structure of a matrix.  We hope that we provide enough
518    high-level matrix routines that few users will need it.
519 
520    `MatGetRow()` always returns 0-based column indices, regardless of
521    whether the internal representation is 0-based (default) or 1-based.
522 
523    For better efficiency, set cols and/or vals to `NULL` if you do
524    not wish to extract these quantities.
525 
526    The user can only examine the values extracted with `MatGetRow()`;
527    the values cannot be altered.  To change the matrix entries, one
528    must use `MatSetValues()`.
529 
530    You can only have one call to `MatGetRow()` outstanding for a particular
531    matrix at a time, per processor. `MatGetRow()` can only obtain rows
532    associated with the given processor, it cannot get rows from the
533    other processors; for that we suggest using `MatCreateSubMatrices()`, then
534    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
535    is in the global number of rows.
536 
537    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
538 
539    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
540 
541    Fortran Note:
542    The calling sequence is
543 .vb
544    MatGetRow(matrix,row,ncols,cols,values,ierr)
545          Mat     matrix (input)
546          integer row    (input)
547          integer ncols  (output)
548          integer cols(maxcols) (output)
549          double precision (or double complex) values(maxcols) output
550 .ve
551    where maxcols >= maximum nonzeros in any row of the matrix.
552 
553    Caution:
554    Do not try to change the contents of the output arrays (cols and vals).
555    In some cases, this may corrupt the matrix.
556 
557 .seealso: `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
558 @*/
559 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
560 {
561   PetscInt incols;
562 
563   PetscFunctionBegin;
564   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
565   PetscValidType(mat, 1);
566   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
567   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
568   MatCheckPreallocated(mat, 1);
569   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);
570   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
571   PetscCall((*mat->ops->getrow)(mat, row, &incols, (PetscInt **)cols, (PetscScalar **)vals));
572   if (ncols) *ncols = incols;
573   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
574   PetscFunctionReturn(PETSC_SUCCESS);
575 }
576 
577 /*@
578    MatConjugate - replaces the matrix values with their complex conjugates
579 
580    Logically Collective
581 
582    Input Parameters:
583 .  mat - the matrix
584 
585    Level: advanced
586 
587 .seealso: `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
588 @*/
589 PetscErrorCode MatConjugate(Mat mat)
590 {
591   PetscFunctionBegin;
592   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
593   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
594   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
595     PetscUseTypeMethod(mat, conjugate);
596     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
597   }
598   PetscFunctionReturn(PETSC_SUCCESS);
599 }
600 
601 /*@C
602    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
603 
604    Not Collective
605 
606    Input Parameters:
607 +  mat - the matrix
608 .  row - the row to get
609 .  ncols, cols - the number of nonzeros and their columns
610 -  vals - if nonzero the column values
611 
612    Level: advanced
613 
614    Notes:
615    This routine should be called after you have finished examining the entries.
616 
617    This routine zeros out `ncols`, `cols`, and `vals`. This is to prevent accidental
618    us of the array after it has been restored. If you pass `NULL`, it will
619    not zero the pointers.  Use of `cols` or `vals` after `MatRestoreRow()` is invalid.
620 
621    Fortran Notes:
622    The calling sequence is
623 .vb
624    MatRestoreRow(matrix,row,ncols,cols,values,ierr)
625       Mat     matrix (input)
626       integer row    (input)
627       integer ncols  (output)
628       integer cols(maxcols) (output)
629       double precision (or double complex) values(maxcols) output
630 .ve
631    Where maxcols >= maximum nonzeros in any row of the matrix.
632 
633    In Fortran `MatRestoreRow()` MUST be called after `MatGetRow()`
634    before another call to `MatGetRow()` can be made.
635 
636 .seealso: `Mat`, `MatGetRow()`
637 @*/
638 PetscErrorCode MatRestoreRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
639 {
640   PetscFunctionBegin;
641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
642   if (ncols) PetscValidIntPointer(ncols, 3);
643   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
644   if (!mat->ops->restorerow) PetscFunctionReturn(PETSC_SUCCESS);
645   PetscCall((*mat->ops->restorerow)(mat, row, ncols, (PetscInt **)cols, (PetscScalar **)vals));
646   if (ncols) *ncols = 0;
647   if (cols) *cols = NULL;
648   if (vals) *vals = NULL;
649   PetscFunctionReturn(PETSC_SUCCESS);
650 }
651 
652 /*@
653    MatGetRowUpperTriangular - Sets a flag to enable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
654    You should call `MatRestoreRowUpperTriangular()` after calling` MatGetRow()` and `MatRestoreRow()` to disable the flag.
655 
656    Not Collective
657 
658    Input Parameters:
659 .  mat - the matrix
660 
661    Level: advanced
662 
663    Note:
664    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.
665 
666 .seealso: `Mat`, `MATSBAIJ`, `MatRestoreRowUpperTriangular()`
667 @*/
668 PetscErrorCode MatGetRowUpperTriangular(Mat mat)
669 {
670   PetscFunctionBegin;
671   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
672   PetscValidType(mat, 1);
673   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
674   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
675   MatCheckPreallocated(mat, 1);
676   if (!mat->ops->getrowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
677   PetscUseTypeMethod(mat, getrowuppertriangular);
678   PetscFunctionReturn(PETSC_SUCCESS);
679 }
680 
681 /*@
682    MatRestoreRowUpperTriangular - Disable calls to `MatGetRow()` for matrix in `MATSBAIJ` format.
683 
684    Not Collective
685 
686    Input Parameters:
687 .  mat - the matrix
688 
689    Level: advanced
690 
691    Note:
692    This routine should be called after you have finished calls to `MatGetRow()` and `MatRestoreRow()`.
693 
694 .seealso: `Mat`, `MATSBAIJ`, `MatGetRowUpperTriangular()`
695 @*/
696 PetscErrorCode MatRestoreRowUpperTriangular(Mat mat)
697 {
698   PetscFunctionBegin;
699   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
700   PetscValidType(mat, 1);
701   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
702   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
703   MatCheckPreallocated(mat, 1);
704   if (!mat->ops->restorerowuppertriangular) PetscFunctionReturn(PETSC_SUCCESS);
705   PetscUseTypeMethod(mat, restorerowuppertriangular);
706   PetscFunctionReturn(PETSC_SUCCESS);
707 }
708 
709 /*@C
710    MatSetOptionsPrefix - Sets the prefix used for searching for all
711    `Mat` options in the database.
712 
713    Logically Collective
714 
715    Input Parameters:
716 +  A - the matrix
717 -  prefix - the prefix to prepend to all option names
718 
719    Level: advanced
720 
721    Notes:
722    A hyphen (-) must NOT be given at the beginning of the prefix name.
723    The first character of all runtime options is AUTOMATICALLY the hyphen.
724 
725    This is NOT used for options for the factorization of the matrix. Normally the
726    prefix is automatically passed in from the PC calling the factorization. To set
727    it directly use  `MatSetOptionsPrefixFactor()`
728 
729 .seealso: `Mat`, `MatSetFromOptions()`, `MatSetOptionsPrefixFactor()`
730 @*/
731 PetscErrorCode MatSetOptionsPrefix(Mat A, const char prefix[])
732 {
733   PetscFunctionBegin;
734   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
735   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)A, prefix));
736   PetscFunctionReturn(PETSC_SUCCESS);
737 }
738 
739 /*@C
740    MatSetOptionsPrefixFactor - Sets the prefix used for searching for all matrix factor options in the database for
741    for matrices created with `MatGetFactor()`
742 
743    Logically Collective
744 
745    Input Parameters:
746 +  A - the matrix
747 -  prefix - the prefix to prepend to all option names for the factored matrix
748 
749    Level: developer
750 
751    Notes:
752    A hyphen (-) must NOT be given at the beginning of the prefix name.
753    The first character of all runtime options is AUTOMATICALLY the hyphen.
754 
755    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
756    it directly when not using `KSP`/`PC` use  `MatSetOptionsPrefixFactor()`
757 
758 .seealso: `Mat`,   [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSetFromOptions()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`
759 @*/
760 PetscErrorCode MatSetOptionsPrefixFactor(Mat A, const char prefix[])
761 {
762   PetscFunctionBegin;
763   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
764   if (prefix) {
765     PetscValidCharPointer(prefix, 2);
766     PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
767     if (prefix != A->factorprefix) {
768       PetscCall(PetscFree(A->factorprefix));
769       PetscCall(PetscStrallocpy(prefix, &A->factorprefix));
770     }
771   } else PetscCall(PetscFree(A->factorprefix));
772   PetscFunctionReturn(PETSC_SUCCESS);
773 }
774 
775 /*@C
776    MatAppendOptionsPrefixFactor - Appends to the prefix used for searching for all matrix factor options in the database for
777    for matrices created with `MatGetFactor()`
778 
779    Logically Collective
780 
781    Input Parameters:
782 +  A - the matrix
783 -  prefix - the prefix to prepend to all option names for the factored matrix
784 
785    Level: developer
786 
787    Notes:
788    A hyphen (-) must NOT be given at the beginning of the prefix name.
789    The first character of all runtime options is AUTOMATICALLY the hyphen.
790 
791    Normally the prefix is automatically passed in from the `PC` calling the factorization. To set
792    it directly when not using `KSP`/`PC` use  `MatAppendOptionsPrefixFactor()`
793 
794 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, PetscOptionsCreate()`, `PetscOptionsDestroy()`, `PetscObjectSetOptionsPrefix()`, `PetscObjectPrependOptionsPrefix()`,
795           `PetscObjectGetOptionsPrefix()`, `TSAppendOptionsPrefix()`, `SNESAppendOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `MatSetOptionsPrefixFactor()`,
796           `MatSetOptionsPrefix()`
797 @*/
798 PetscErrorCode MatAppendOptionsPrefixFactor(Mat A, const char prefix[])
799 {
800   char  *buf = A->factorprefix;
801   size_t len1, len2;
802 
803   PetscFunctionBegin;
804   PetscValidHeader(A, 1);
805   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
806   if (!buf) {
807     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
808     PetscFunctionReturn(PETSC_SUCCESS);
809   }
810   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
811 
812   PetscCall(PetscStrlen(prefix, &len1));
813   PetscCall(PetscStrlen(buf, &len2));
814   PetscCall(PetscMalloc1(1 + len1 + len2, &A->factorprefix));
815   PetscCall(PetscStrcpy(A->factorprefix, buf));
816   PetscCall(PetscStrcat(A->factorprefix, prefix));
817   PetscCall(PetscFree(buf));
818   PetscFunctionReturn(PETSC_SUCCESS);
819 }
820 
821 /*@C
822    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
823    matrix options in the database.
824 
825    Logically Collective
826 
827    Input Parameters:
828 +  A - the matrix
829 -  prefix - the prefix to prepend to all option names
830 
831    Level: advanced
832 
833    Note:
834    A hyphen (-) must NOT be given at the beginning of the prefix name.
835    The first character of all runtime options is AUTOMATICALLY the hyphen.
836 
837 .seealso: `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
838 @*/
839 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
840 {
841   PetscFunctionBegin;
842   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
843   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
844   PetscFunctionReturn(PETSC_SUCCESS);
845 }
846 
847 /*@C
848    MatGetOptionsPrefix - Gets the prefix used for searching for all
849    matrix options in the database.
850 
851    Not Collective
852 
853    Input Parameter:
854 .  A - the matrix
855 
856    Output Parameter:
857 .  prefix - pointer to the prefix string used
858 
859    Level: advanced
860 
861    Fortran Note:
862    The user should pass in a string `prefix` of
863    sufficient length to hold the prefix.
864 
865 .seealso: `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
866 @*/
867 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
868 {
869   PetscFunctionBegin;
870   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
871   PetscValidPointer(prefix, 2);
872   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
873   PetscFunctionReturn(PETSC_SUCCESS);
874 }
875 
876 /*@
877    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
878 
879    Collective
880 
881    Input Parameters:
882 .  A - the matrix
883 
884    Level: beginner
885 
886    Notes:
887    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
888 
889    Users can reset the preallocation to access the original memory.
890 
891    Currently only supported for  `MATMPIAIJ` and `MATSEQAIJ` matrices.
892 
893 .seealso: `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
894 @*/
895 PetscErrorCode MatResetPreallocation(Mat A)
896 {
897   PetscFunctionBegin;
898   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
899   PetscValidType(A, 1);
900   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
901   PetscFunctionReturn(PETSC_SUCCESS);
902 }
903 
904 /*@
905    MatSetUp - Sets up the internal matrix data structures for later use.
906 
907    Collective
908 
909    Input Parameters:
910 .  A - the matrix
911 
912    Level: intermediate
913 
914    Notes:
915    If the user has not set preallocation for this matrix then a default preallocation that is likely to be inefficient is used.
916 
917    If a suitable preallocation routine is used, this function does not need to be called.
918 
919    See the Performance chapter of the PETSc users manual for how to preallocate matrices
920 
921    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
922 
923 .seealso: `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`
924 @*/
925 PetscErrorCode MatSetUp(Mat A)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
929   if (!((PetscObject)A)->type_name) {
930     PetscMPIInt size;
931 
932     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
933     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
934   }
935   if (!A->preallocated) PetscTryTypeMethod(A, setup);
936   PetscCall(PetscLayoutSetUp(A->rmap));
937   PetscCall(PetscLayoutSetUp(A->cmap));
938   A->preallocated = PETSC_TRUE;
939   PetscFunctionReturn(PETSC_SUCCESS);
940 }
941 
942 #if defined(PETSC_HAVE_SAWS)
943   #include <petscviewersaws.h>
944 #endif
945 
946 /*@C
947    MatViewFromOptions - View properties of the matrix from the options database
948 
949    Collective
950 
951    Input Parameters:
952 +  A - the matrix
953 .  obj - optional additional object that provides the options prefix to use
954 -  name - command line option
955 
956   Options Database Key:
957 .  -mat_view [viewertype]:... - the viewer and its options
958 
959    Level: intermediate
960 
961   Notes:
962 .vb
963     If no value is provided ascii:stdout is used
964        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
965                                                   for example ascii::ascii_info prints just the information about the object not all details
966                                                   unless :append is given filename opens in write mode, overwriting what was already there
967        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
968        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
969        socket[:port]                             defaults to the standard output port
970        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
971 .ve
972 
973 .seealso: `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
974 @*/
975 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
976 {
977   PetscFunctionBegin;
978   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
979   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
980   PetscFunctionReturn(PETSC_SUCCESS);
981 }
982 
983 /*@C
984    MatView - display information about a matrix in a variety ways
985 
986    Collective
987 
988    Input Parameters:
989 +  mat - the matrix
990 -  viewer - visualization context
991 
992   Notes:
993   The available visualization contexts include
994 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
995 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
996 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
997 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
998 
999    The user can open alternative visualization contexts with
1000 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1001 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1002          specified file; corresponding input uses MatLoad()
1003 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1004          an X window display
1005 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1006          Currently only the sequential dense and AIJ
1007          matrix types support the Socket viewer.
1008 
1009    The user can call `PetscViewerPushFormat()` to specify the output
1010    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1011    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1012 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1013 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1014 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1015 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1016          format common among all matrix types
1017 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1018          format (which is in many cases the same as the default)
1019 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1020          size and structure (not the matrix entries)
1021 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1022          the matrix structure
1023 
1024    Options Database Keys:
1025 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
1026 .  -mat_view ::ascii_info_detail - Prints more detailed info
1027 .  -mat_view - Prints matrix in ASCII format
1028 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
1029 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
1030 .  -display <name> - Sets display name (default is host)
1031 .  -draw_pause <sec> - Sets number of seconds to pause after display
1032 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
1033 .  -viewer_socket_machine <machine> -
1034 .  -viewer_socket_port <port> -
1035 .  -mat_view binary - save matrix to file in binary format
1036 -  -viewer_binary_filename <name> -
1037 
1038    Level: beginner
1039 
1040    Notes:
1041     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1042     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1043 
1044     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1045 
1046     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1047       viewer is used.
1048 
1049       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1050       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1051 
1052       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1053       and then use the following mouse functions.
1054 .vb
1055   left mouse: zoom in
1056   middle mouse: zoom out
1057   right mouse: continue with the simulation
1058 .ve
1059 
1060 .seealso: `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1061           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1062 @*/
1063 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1064 {
1065   PetscInt          rows, cols, rbs, cbs;
1066   PetscBool         isascii, isstring, issaws;
1067   PetscViewerFormat format;
1068   PetscMPIInt       size;
1069 
1070   PetscFunctionBegin;
1071   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1072   PetscValidType(mat, 1);
1073   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1074   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1075   PetscCheckSameComm(mat, 1, viewer, 2);
1076 
1077   PetscCall(PetscViewerGetFormat(viewer, &format));
1078   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1079   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1080 
1081   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1082   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1083   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1084   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");
1085 
1086   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1087   if (isascii) {
1088     if (!mat->preallocated) {
1089       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1090       PetscFunctionReturn(PETSC_SUCCESS);
1091     }
1092     if (!mat->assembled) {
1093       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1094       PetscFunctionReturn(PETSC_SUCCESS);
1095     }
1096     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1097     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1098       MatNullSpace nullsp, transnullsp;
1099 
1100       PetscCall(PetscViewerASCIIPushTab(viewer));
1101       PetscCall(MatGetSize(mat, &rows, &cols));
1102       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1103       if (rbs != 1 || cbs != 1) {
1104         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1105         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1106       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1107       if (mat->factortype) {
1108         MatSolverType solver;
1109         PetscCall(MatFactorGetSolverType(mat, &solver));
1110         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1111       }
1112       if (mat->ops->getinfo) {
1113         MatInfo info;
1114         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1115         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1116         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1117       }
1118       PetscCall(MatGetNullSpace(mat, &nullsp));
1119       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1120       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1121       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1122       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1123       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1124       PetscCall(PetscViewerASCIIPushTab(viewer));
1125       PetscCall(MatProductView(mat, viewer));
1126       PetscCall(PetscViewerASCIIPopTab(viewer));
1127     }
1128   } else if (issaws) {
1129 #if defined(PETSC_HAVE_SAWS)
1130     PetscMPIInt rank;
1131 
1132     PetscCall(PetscObjectName((PetscObject)mat));
1133     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1134     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1135 #endif
1136   } else if (isstring) {
1137     const char *type;
1138     PetscCall(MatGetType(mat, &type));
1139     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1140     PetscTryTypeMethod(mat, view, viewer);
1141   }
1142   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1143     PetscCall(PetscViewerASCIIPushTab(viewer));
1144     PetscUseTypeMethod(mat, viewnative, viewer);
1145     PetscCall(PetscViewerASCIIPopTab(viewer));
1146   } else if (mat->ops->view) {
1147     PetscCall(PetscViewerASCIIPushTab(viewer));
1148     PetscUseTypeMethod(mat, view, viewer);
1149     PetscCall(PetscViewerASCIIPopTab(viewer));
1150   }
1151   if (isascii) {
1152     PetscCall(PetscViewerGetFormat(viewer, &format));
1153     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1154   }
1155   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1156   PetscFunctionReturn(PETSC_SUCCESS);
1157 }
1158 
1159 #if defined(PETSC_USE_DEBUG)
1160   #include <../src/sys/totalview/tv_data_display.h>
1161 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1162 {
1163   TV_add_row("Local rows", "int", &mat->rmap->n);
1164   TV_add_row("Local columns", "int", &mat->cmap->n);
1165   TV_add_row("Global rows", "int", &mat->rmap->N);
1166   TV_add_row("Global columns", "int", &mat->cmap->N);
1167   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1168   return TV_format_OK;
1169 }
1170 #endif
1171 
1172 /*@C
1173    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1174    with `MatView()`.  The matrix format is determined from the options database.
1175    Generates a parallel MPI matrix if the communicator has more than one
1176    processor.  The default matrix type is `MATAIJ`.
1177 
1178    Collective
1179 
1180    Input Parameters:
1181 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1182             or some related function before a call to `MatLoad()`
1183 -  viewer - binary/HDF5 file viewer
1184 
1185    Options Database Keys:
1186    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1187    block size
1188 .    -matload_block_size <bs> - set block size
1189 
1190    Level: beginner
1191 
1192    Notes:
1193    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1194    `Mat` before calling this routine if you wish to set it from the options database.
1195 
1196    `MatLoad()` automatically loads into the options database any options
1197    given in the file filename.info where filename is the name of the file
1198    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1199    file will be ignored if you use the -viewer_binary_skip_info option.
1200 
1201    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1202    sets the default matrix type AIJ and sets the local and global sizes.
1203    If type and/or size is already set, then the same are used.
1204 
1205    In parallel, each processor can load a subset of rows (or the
1206    entire matrix).  This routine is especially useful when a large
1207    matrix is stored on disk and only part of it is desired on each
1208    processor.  For example, a parallel solver may access only some of
1209    the rows from each processor.  The algorithm used here reads
1210    relatively small blocks of data rather than reading the entire
1211    matrix and then subsetting it.
1212 
1213    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1214    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1215    or the sequence like
1216 .vb
1217     `PetscViewer` v;
1218     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1219     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1220     `PetscViewerSetFromOptions`(v);
1221     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1222     `PetscViewerFileSetName`(v,"datafile");
1223 .ve
1224    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1225 $ -viewer_type {binary,hdf5}
1226 
1227    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1228    and src/mat/tutorials/ex10.c with the second approach.
1229 
1230    Notes:
1231    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1232    is read onto rank 0 and then shipped to its destination rank, one after another.
1233    Multiple objects, both matrices and vectors, can be stored within the same file.
1234    Their PetscObject name is ignored; they are loaded in the order of their storage.
1235 
1236    Most users should not need to know the details of the binary storage
1237    format, since `MatLoad()` and `MatView()` completely hide these details.
1238    But for anyone who's interested, the standard binary matrix storage
1239    format is
1240 
1241 $    PetscInt    MAT_FILE_CLASSID
1242 $    PetscInt    number of rows
1243 $    PetscInt    number of columns
1244 $    PetscInt    total number of nonzeros
1245 $    PetscInt    *number nonzeros in each row
1246 $    PetscInt    *column indices of all nonzeros (starting index is zero)
1247 $    PetscScalar *values of all nonzeros
1248 
1249    PETSc automatically does the byte swapping for
1250 machines that store the bytes reversed, e.g.  DEC alpha, freebsd,
1251 Linux, Microsoft Windows and the Intel Paragon; thus if you write your own binary
1252 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1253 and `PetscBinaryWrite()` to see how this may be done.
1254 
1255    Notes:
1256    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1257    Each processor's chunk is loaded independently by its owning rank.
1258    Multiple objects, both matrices and vectors, can be stored within the same file.
1259    They are looked up by their PetscObject name.
1260 
1261    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1262    by default the same structure and naming of the AIJ arrays and column count
1263    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1264 $    save example.mat A b -v7.3
1265    can be directly read by this routine (see Reference 1 for details).
1266 
1267    Depending on your MATLAB version, this format might be a default,
1268    otherwise you can set it as default in Preferences.
1269 
1270    Unless -nocompression flag is used to save the file in MATLAB,
1271    PETSc must be configured with ZLIB package.
1272 
1273    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1274 
1275    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1276 
1277    Corresponding `MatView()` is not yet implemented.
1278 
1279    The loaded matrix is actually a transpose of the original one in MATLAB,
1280    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1281    With this format, matrix is automatically transposed by PETSc,
1282    unless the matrix is marked as SPD or symmetric
1283    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1284 
1285    References:
1286 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1287 
1288 .seealso: `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1289  @*/
1290 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1291 {
1292   PetscBool flg;
1293 
1294   PetscFunctionBegin;
1295   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1296   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1297 
1298   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1299 
1300   flg = PETSC_FALSE;
1301   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1302   if (flg) {
1303     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1304     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1305   }
1306   flg = PETSC_FALSE;
1307   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1308   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1309 
1310   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1311   PetscUseTypeMethod(mat, load, viewer);
1312   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1313   PetscFunctionReturn(PETSC_SUCCESS);
1314 }
1315 
1316 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1317 {
1318   Mat_Redundant *redund = *redundant;
1319 
1320   PetscFunctionBegin;
1321   if (redund) {
1322     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1323       PetscCall(ISDestroy(&redund->isrow));
1324       PetscCall(ISDestroy(&redund->iscol));
1325       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1326     } else {
1327       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1328       PetscCall(PetscFree(redund->sbuf_j));
1329       PetscCall(PetscFree(redund->sbuf_a));
1330       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1331         PetscCall(PetscFree(redund->rbuf_j[i]));
1332         PetscCall(PetscFree(redund->rbuf_a[i]));
1333       }
1334       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1335     }
1336 
1337     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1338     PetscCall(PetscFree(redund));
1339   }
1340   PetscFunctionReturn(PETSC_SUCCESS);
1341 }
1342 
1343 /*@C
1344    MatDestroy - Frees space taken by a matrix.
1345 
1346    Collective
1347 
1348    Input Parameter:
1349 .  A - the matrix
1350 
1351    Level: beginner
1352 
1353    Developer Note:
1354    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1355    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1356    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1357    if changes are needed here.
1358 
1359 .seealso: `Mat`, `MatCreate()`
1360 @*/
1361 PetscErrorCode MatDestroy(Mat *A)
1362 {
1363   PetscFunctionBegin;
1364   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1365   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1366   if (--((PetscObject)(*A))->refct > 0) {
1367     *A = NULL;
1368     PetscFunctionReturn(PETSC_SUCCESS);
1369   }
1370 
1371   /* if memory was published with SAWs then destroy it */
1372   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1373   PetscTryTypeMethod((*A), destroy);
1374 
1375   PetscCall(PetscFree((*A)->factorprefix));
1376   PetscCall(PetscFree((*A)->defaultvectype));
1377   PetscCall(PetscFree((*A)->defaultrandtype));
1378   PetscCall(PetscFree((*A)->bsizes));
1379   PetscCall(PetscFree((*A)->solvertype));
1380   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1381   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1382   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1383   PetscCall(MatProductClear(*A));
1384   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1385   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1386   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1387   PetscCall(MatDestroy(&(*A)->schur));
1388   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1389   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1390   PetscCall(PetscHeaderDestroy(A));
1391   PetscFunctionReturn(PETSC_SUCCESS);
1392 }
1393 
1394 /*@C
1395    MatSetValues - Inserts or adds a block of values into a matrix.
1396    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1397    MUST be called after all calls to `MatSetValues()` have been completed.
1398 
1399    Not Collective
1400 
1401    Input Parameters:
1402 +  mat - the matrix
1403 .  v - a logically two-dimensional array of values
1404 .  m, idxm - the number of rows and their global indices
1405 .  n, idxn - the number of columns and their global indices
1406 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1407 
1408    Level: beginner
1409 
1410    Notes:
1411    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1412       `MatSetUp()` before using this routine
1413 
1414    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1415 
1416    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1417    options cannot be mixed without intervening calls to the assembly
1418    routines.
1419 
1420    `MatSetValues()` uses 0-based row and column numbers in Fortran
1421    as well as in C.
1422 
1423    Negative indices may be passed in idxm and idxn, these rows and columns are
1424    simply ignored. This allows easily inserting element stiffness matrices
1425    with homogeneous Dirchlet boundary conditions that you don't want represented
1426    in the matrix.
1427 
1428    Efficiency Alert:
1429    The routine `MatSetValuesBlocked()` may offer much better efficiency
1430    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1431 
1432    Developer Note:
1433    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1434    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1435 
1436 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1437           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1438 @*/
1439 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1440 {
1441   PetscFunctionBeginHot;
1442   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1443   PetscValidType(mat, 1);
1444   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1445   PetscValidIntPointer(idxm, 3);
1446   PetscValidIntPointer(idxn, 5);
1447   MatCheckPreallocated(mat, 1);
1448 
1449   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1450   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1451 
1452   if (PetscDefined(USE_DEBUG)) {
1453     PetscInt i, j;
1454 
1455     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1456     for (i = 0; i < m; i++) {
1457       for (j = 0; j < n; j++) {
1458         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1459 #if defined(PETSC_USE_COMPLEX)
1460           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]);
1461 #else
1462           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]);
1463 #endif
1464       }
1465     }
1466     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);
1467     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);
1468   }
1469 
1470   if (mat->assembled) {
1471     mat->was_assembled = PETSC_TRUE;
1472     mat->assembled     = PETSC_FALSE;
1473   }
1474   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1475   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1476   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1477   PetscFunctionReturn(PETSC_SUCCESS);
1478 }
1479 
1480 /*@C
1481    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1482    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1483    MUST be called after all calls to `MatSetValues()` have been completed.
1484 
1485    Not Collective
1486 
1487    Input Parameters:
1488 +  mat - the matrix
1489 .  v - a logically two-dimensional array of values
1490 .  ism - the rows to provide
1491 .  isn - the columns to provide
1492 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1493 
1494    Level: beginner
1495 
1496    Notes:
1497    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
1498       `MatSetUp()` before using this routine
1499 
1500    By default the values, v, are row-oriented. See `MatSetOption()` for other options.
1501 
1502    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1503    options cannot be mixed without intervening calls to the assembly
1504    routines.
1505 
1506    `MatSetValues()` uses 0-based row and column numbers in Fortran
1507    as well as in C.
1508 
1509    Negative indices may be passed in ism and isn, these rows and columns are
1510    simply ignored. This allows easily inserting element stiffness matrices
1511    with homogeneous Dirchlet boundary conditions that you don't want represented
1512    in the matrix.
1513 
1514    Efficiency Alert:
1515    The routine `MatSetValuesBlocked()` may offer much better efficiency
1516    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1517 
1518     This is currently not optimized for any particular `ISType`
1519 
1520    Developer Notes:
1521     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1522                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1523 
1524 .seealso: `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1525           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1526 @*/
1527 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1528 {
1529   PetscInt        m, n;
1530   const PetscInt *rows, *cols;
1531 
1532   PetscFunctionBeginHot;
1533   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1534   PetscCall(ISGetIndices(ism, &rows));
1535   PetscCall(ISGetIndices(isn, &cols));
1536   PetscCall(ISGetLocalSize(ism, &m));
1537   PetscCall(ISGetLocalSize(isn, &n));
1538   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1539   PetscCall(ISRestoreIndices(ism, &rows));
1540   PetscCall(ISRestoreIndices(isn, &cols));
1541   PetscFunctionReturn(PETSC_SUCCESS);
1542 }
1543 
1544 /*@
1545    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1546         values into a matrix
1547 
1548    Not Collective
1549 
1550    Input Parameters:
1551 +  mat - the matrix
1552 .  row - the (block) row to set
1553 -  v - a logically two-dimensional array of values
1554 
1555    Level: intermediate
1556 
1557    Notes:
1558    The values, `v`, are column-oriented (for the block version) and sorted
1559 
1560    All the nonzeros in the row must be provided
1561 
1562    The matrix must have previously had its column indices set
1563 
1564    The row must belong to this process
1565 
1566 .seealso: `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1567           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1568 @*/
1569 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1570 {
1571   PetscInt globalrow;
1572 
1573   PetscFunctionBegin;
1574   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1575   PetscValidType(mat, 1);
1576   PetscValidScalarPointer(v, 3);
1577   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1578   PetscCall(MatSetValuesRow(mat, globalrow, v));
1579   PetscFunctionReturn(PETSC_SUCCESS);
1580 }
1581 
1582 /*@
1583    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1584         values into a matrix
1585 
1586    Not Collective
1587 
1588    Input Parameters:
1589 +  mat - the matrix
1590 .  row - the (block) row to set
1591 -  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
1592 
1593    Level: advanced
1594 
1595    Notes:
1596    The values, `v`, are column-oriented for the block version.
1597 
1598    All the nonzeros in the row must be provided
1599 
1600    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1601 
1602    The row must belong to this process
1603 
1604 .seealso: `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1605           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1606 @*/
1607 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1608 {
1609   PetscFunctionBeginHot;
1610   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1611   PetscValidType(mat, 1);
1612   MatCheckPreallocated(mat, 1);
1613   PetscValidScalarPointer(v, 3);
1614   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1615   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1616   mat->insertmode = INSERT_VALUES;
1617 
1618   if (mat->assembled) {
1619     mat->was_assembled = PETSC_TRUE;
1620     mat->assembled     = PETSC_FALSE;
1621   }
1622   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1623   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1624   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1625   PetscFunctionReturn(PETSC_SUCCESS);
1626 }
1627 
1628 /*@
1629    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1630      Using structured grid indexing
1631 
1632    Not Collective
1633 
1634    Input Parameters:
1635 +  mat - the matrix
1636 .  m - number of rows being entered
1637 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1638 .  n - number of columns being entered
1639 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1640 .  v - a logically two-dimensional array of values
1641 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1642 
1643    Level: beginner
1644 
1645    Notes:
1646    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1647 
1648    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1649    options cannot be mixed without intervening calls to the assembly
1650    routines.
1651 
1652    The grid coordinates are across the entire grid, not just the local portion
1653 
1654    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1655    as well as in C.
1656 
1657    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1658 
1659    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1660    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1661 
1662    The columns and rows in the stencil passed in MUST be contained within the
1663    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1664    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1665    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1666    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1667 
1668    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1669    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1670    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1671    `DM_BOUNDARY_PERIODIC` boundary type.
1672 
1673    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
1674    a single value per point) you can skip filling those indices.
1675 
1676    Inspired by the structured grid interface to the HYPRE package
1677    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1678 
1679    Efficiency Alert:
1680    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1681    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1682 
1683    Fortran Note:
1684    `idxm` and `idxn` should be declared as
1685 $     MatStencil idxm(4,m),idxn(4,n)
1686    and the values inserted using
1687 .vb
1688     idxm(MatStencil_i,1) = i
1689     idxm(MatStencil_j,1) = j
1690     idxm(MatStencil_k,1) = k
1691     idxm(MatStencil_c,1) = c
1692     etc
1693 .ve
1694 
1695 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1696           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1697 @*/
1698 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1699 {
1700   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1701   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1702   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1703 
1704   PetscFunctionBegin;
1705   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1706   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1707   PetscValidType(mat, 1);
1708   PetscValidPointer(idxm, 3);
1709   PetscValidPointer(idxn, 5);
1710 
1711   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1712     jdxm = buf;
1713     jdxn = buf + m;
1714   } else {
1715     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1716     jdxm = bufm;
1717     jdxn = bufn;
1718   }
1719   for (i = 0; i < m; i++) {
1720     for (j = 0; j < 3 - sdim; j++) dxm++;
1721     tmp = *dxm++ - starts[0];
1722     for (j = 0; j < dim - 1; j++) {
1723       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1724       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1725     }
1726     if (mat->stencil.noc) dxm++;
1727     jdxm[i] = tmp;
1728   }
1729   for (i = 0; i < n; i++) {
1730     for (j = 0; j < 3 - sdim; j++) dxn++;
1731     tmp = *dxn++ - starts[0];
1732     for (j = 0; j < dim - 1; j++) {
1733       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1734       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1735     }
1736     if (mat->stencil.noc) dxn++;
1737     jdxn[i] = tmp;
1738   }
1739   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1740   PetscCall(PetscFree2(bufm, bufn));
1741   PetscFunctionReturn(PETSC_SUCCESS);
1742 }
1743 
1744 /*@
1745    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1746      Using structured grid indexing
1747 
1748    Not Collective
1749 
1750    Input Parameters:
1751 +  mat - the matrix
1752 .  m - number of rows being entered
1753 .  idxm - grid coordinates for matrix rows being entered
1754 .  n - number of columns being entered
1755 .  idxn - grid coordinates for matrix columns being entered
1756 .  v - a logically two-dimensional array of values
1757 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1758 
1759    Level: beginner
1760 
1761    Notes:
1762    By default the values, `v`, are row-oriented and unsorted.
1763    See `MatSetOption()` for other options.
1764 
1765    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1766    options cannot be mixed without intervening calls to the assembly
1767    routines.
1768 
1769    The grid coordinates are across the entire grid, not just the local portion
1770 
1771    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1772    as well as in C.
1773 
1774    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1775 
1776    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1777    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1778 
1779    The columns and rows in the stencil passed in MUST be contained within the
1780    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1781    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1782    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1783    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1784 
1785    Negative indices may be passed in idxm and idxn, these rows and columns are
1786    simply ignored. This allows easily inserting element stiffness matrices
1787    with homogeneous Dirchlet boundary conditions that you don't want represented
1788    in the matrix.
1789 
1790    Inspired by the structured grid interface to the HYPRE package
1791    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1792 
1793    Fortran Note:
1794    `idxm` and `idxn` should be declared as
1795 $     MatStencil idxm(4,m),idxn(4,n)
1796    and the values inserted using
1797 .vb
1798     idxm(MatStencil_i,1) = i
1799     idxm(MatStencil_j,1) = j
1800     idxm(MatStencil_k,1) = k
1801    etc
1802 .ve
1803 
1804 .seealso: `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1805           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1806           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1807 @*/
1808 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1809 {
1810   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1811   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1812   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1813 
1814   PetscFunctionBegin;
1815   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1816   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1817   PetscValidType(mat, 1);
1818   PetscValidPointer(idxm, 3);
1819   PetscValidPointer(idxn, 5);
1820   PetscValidScalarPointer(v, 6);
1821 
1822   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1823     jdxm = buf;
1824     jdxn = buf + m;
1825   } else {
1826     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1827     jdxm = bufm;
1828     jdxn = bufn;
1829   }
1830   for (i = 0; i < m; i++) {
1831     for (j = 0; j < 3 - sdim; j++) dxm++;
1832     tmp = *dxm++ - starts[0];
1833     for (j = 0; j < sdim - 1; j++) {
1834       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1835       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1836     }
1837     dxm++;
1838     jdxm[i] = tmp;
1839   }
1840   for (i = 0; i < n; i++) {
1841     for (j = 0; j < 3 - sdim; j++) dxn++;
1842     tmp = *dxn++ - starts[0];
1843     for (j = 0; j < sdim - 1; j++) {
1844       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1845       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1846     }
1847     dxn++;
1848     jdxn[i] = tmp;
1849   }
1850   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1851   PetscCall(PetscFree2(bufm, bufn));
1852   PetscFunctionReturn(PETSC_SUCCESS);
1853 }
1854 
1855 /*@
1856    MatSetStencil - Sets the grid information for setting values into a matrix via
1857         `MatSetValuesStencil()`
1858 
1859    Not Collective
1860 
1861    Input Parameters:
1862 +  mat - the matrix
1863 .  dim - dimension of the grid 1, 2, or 3
1864 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1865 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1866 -  dof - number of degrees of freedom per node
1867 
1868    Level: beginner
1869 
1870    Notes:
1871    Inspired by the structured grid interface to the HYPRE package
1872    (www.llnl.gov/CASC/hyper)
1873 
1874    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1875    user.
1876 
1877 .seealso: `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1878           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1879 @*/
1880 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1881 {
1882   PetscFunctionBegin;
1883   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1884   PetscValidIntPointer(dims, 3);
1885   PetscValidIntPointer(starts, 4);
1886 
1887   mat->stencil.dim = dim + (dof > 1);
1888   for (PetscInt i = 0; i < dim; i++) {
1889     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1890     mat->stencil.starts[i] = starts[dim - i - 1];
1891   }
1892   mat->stencil.dims[dim]   = dof;
1893   mat->stencil.starts[dim] = 0;
1894   mat->stencil.noc         = (PetscBool)(dof == 1);
1895   PetscFunctionReturn(PETSC_SUCCESS);
1896 }
1897 
1898 /*@C
1899    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1900 
1901    Not Collective
1902 
1903    Input Parameters:
1904 +  mat - the matrix
1905 .  v - a logically two-dimensional array of values
1906 .  m  - the number of block rows
1907 .  idxm - the global block indices
1908 .  n - the number of block columns
1909 .  idxn - the global block indices
1910 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1911 
1912    Level: intermediate
1913 
1914    Notes:
1915    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1916    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1917 
1918    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1919    NOT the total number of rows/columns; for example, if the block size is 2 and
1920    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1921    The values in idxm would be 1 2; that is the first index for each block divided by
1922    the block size.
1923 
1924    You must call `MatSetBlockSize()` when constructing this matrix (before
1925    preallocating it).
1926 
1927    By default the values, `v`, are row-oriented, so the layout of
1928    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1929 
1930    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1931    options cannot be mixed without intervening calls to the assembly
1932    routines.
1933 
1934    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1935    as well as in C.
1936 
1937    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1938    simply ignored. This allows easily inserting element stiffness matrices
1939    with homogeneous Dirchlet boundary conditions that you don't want represented
1940    in the matrix.
1941 
1942    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1943    internal searching must be done to determine where to place the
1944    data in the matrix storage space.  By instead inserting blocks of
1945    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1946    reduced.
1947 
1948    Example:
1949 .vb
1950    Suppose m=n=2 and block size(bs) = 2 The array is
1951 
1952    1  2  | 3  4
1953    5  6  | 7  8
1954    - - - | - - -
1955    9  10 | 11 12
1956    13 14 | 15 16
1957 
1958    v[] should be passed in like
1959    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1960 
1961   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1962    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1963 .ve
1964 
1965 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1966 @*/
1967 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1968 {
1969   PetscFunctionBeginHot;
1970   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1971   PetscValidType(mat, 1);
1972   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1973   PetscValidIntPointer(idxm, 3);
1974   PetscValidIntPointer(idxn, 5);
1975   MatCheckPreallocated(mat, 1);
1976   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1977   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1978   if (PetscDefined(USE_DEBUG)) {
1979     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1980     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1981   }
1982   if (PetscDefined(USE_DEBUG)) {
1983     PetscInt rbs, cbs, M, N, i;
1984     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1985     PetscCall(MatGetSize(mat, &M, &N));
1986     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);
1987     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);
1988   }
1989   if (mat->assembled) {
1990     mat->was_assembled = PETSC_TRUE;
1991     mat->assembled     = PETSC_FALSE;
1992   }
1993   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1994   if (mat->ops->setvaluesblocked) {
1995     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1996   } else {
1997     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1998     PetscInt i, j, bs, cbs;
1999 
2000     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
2001     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2002       iidxm = buf;
2003       iidxn = buf + m * bs;
2004     } else {
2005       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
2006       iidxm = bufr;
2007       iidxn = bufc;
2008     }
2009     for (i = 0; i < m; i++) {
2010       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2011     }
2012     if (m != n || bs != cbs || idxm != idxn) {
2013       for (i = 0; i < n; i++) {
2014         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2015       }
2016     } else iidxn = iidxm;
2017     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2018     PetscCall(PetscFree2(bufr, bufc));
2019   }
2020   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2021   PetscFunctionReturn(PETSC_SUCCESS);
2022 }
2023 
2024 /*@C
2025    MatGetValues - Gets a block of local values from a matrix.
2026 
2027    Not Collective; can only return values that are owned by the give process
2028 
2029    Input Parameters:
2030 +  mat - the matrix
2031 .  v - a logically two-dimensional array for storing the values
2032 .  m  - the number of rows
2033 .  idxm - the  global indices of the rows
2034 .  n - the number of columns
2035 -  idxn - the global indices of the columns
2036 
2037    Level: advanced
2038 
2039    Notes:
2040      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2041      The values, `v`, are then returned in a row-oriented format,
2042      analogous to that used by default in `MatSetValues()`.
2043 
2044      `MatGetValues()` uses 0-based row and column numbers in
2045      Fortran as well as in C.
2046 
2047      `MatGetValues()` requires that the matrix has been assembled
2048      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2049      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2050      without intermediate matrix assembly.
2051 
2052      Negative row or column indices will be ignored and those locations in `v` will be
2053      left unchanged.
2054 
2055      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2056      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2057      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2058 
2059 .seealso: `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2060 @*/
2061 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2062 {
2063   PetscFunctionBegin;
2064   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2065   PetscValidType(mat, 1);
2066   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2067   PetscValidIntPointer(idxm, 3);
2068   PetscValidIntPointer(idxn, 5);
2069   PetscValidScalarPointer(v, 6);
2070   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2071   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2072   MatCheckPreallocated(mat, 1);
2073 
2074   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2075   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2076   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2077   PetscFunctionReturn(PETSC_SUCCESS);
2078 }
2079 
2080 /*@C
2081    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2082      defined previously by `MatSetLocalToGlobalMapping()`
2083 
2084    Not Collective
2085 
2086    Input Parameters:
2087 +  mat - the matrix
2088 .  nrow - number of rows
2089 .  irow - the row local indices
2090 .  ncol - number of columns
2091 -  icol - the column local indices
2092 
2093    Output Parameter:
2094 .  y -  a logically two-dimensional array of values
2095 
2096    Level: advanced
2097 
2098    Notes:
2099      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2100 
2101      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,
2102      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2103      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2104      with `MatSetLocalToGlobalMapping()`.
2105 
2106    Developer Note:
2107       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2108       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2109 
2110 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2111           `MatSetValuesLocal()`, `MatGetValues()`
2112 @*/
2113 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2114 {
2115   PetscFunctionBeginHot;
2116   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2117   PetscValidType(mat, 1);
2118   MatCheckPreallocated(mat, 1);
2119   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2120   PetscValidIntPointer(irow, 3);
2121   PetscValidIntPointer(icol, 5);
2122   if (PetscDefined(USE_DEBUG)) {
2123     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2124     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2125   }
2126   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2127   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2128   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2129   else {
2130     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2131     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2132       irowm = buf;
2133       icolm = buf + nrow;
2134     } else {
2135       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2136       irowm = bufr;
2137       icolm = bufc;
2138     }
2139     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2140     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2141     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2142     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2143     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2144     PetscCall(PetscFree2(bufr, bufc));
2145   }
2146   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2147   PetscFunctionReturn(PETSC_SUCCESS);
2148 }
2149 
2150 /*@
2151   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2152   the same size. Currently, this can only be called once and creates the given matrix.
2153 
2154   Not Collective
2155 
2156   Input Parameters:
2157 + mat - the matrix
2158 . nb - the number of blocks
2159 . bs - the number of rows (and columns) in each block
2160 . rows - a concatenation of the rows for each block
2161 - v - a concatenation of logically two-dimensional arrays of values
2162 
2163   Level: advanced
2164 
2165   Note:
2166   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2167 
2168   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2169 
2170 .seealso: `Mat`, `Mat`MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2171           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2172 @*/
2173 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2174 {
2175   PetscFunctionBegin;
2176   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2177   PetscValidType(mat, 1);
2178   PetscValidIntPointer(rows, 4);
2179   PetscValidScalarPointer(v, 5);
2180   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2181 
2182   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2183   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2184   else {
2185     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2186   }
2187   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2188   PetscFunctionReturn(PETSC_SUCCESS);
2189 }
2190 
2191 /*@
2192    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2193    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2194    using a local (per-processor) numbering.
2195 
2196    Not Collective
2197 
2198    Input Parameters:
2199 +  x - the matrix
2200 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2201 -  cmapping - column mapping
2202 
2203    Level: intermediate
2204 
2205    Note:
2206    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2207 
2208 .seealso: `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2209 @*/
2210 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2211 {
2212   PetscFunctionBegin;
2213   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2214   PetscValidType(x, 1);
2215   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2216   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2217   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2218   else {
2219     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2220     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2221   }
2222   PetscFunctionReturn(PETSC_SUCCESS);
2223 }
2224 
2225 /*@
2226    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2227 
2228    Not Collective
2229 
2230    Input Parameter:
2231 .  A - the matrix
2232 
2233    Output Parameters:
2234 + rmapping - row mapping
2235 - cmapping - column mapping
2236 
2237    Level: advanced
2238 
2239 .seealso: `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2240 @*/
2241 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2242 {
2243   PetscFunctionBegin;
2244   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2245   PetscValidType(A, 1);
2246   if (rmapping) {
2247     PetscValidPointer(rmapping, 2);
2248     *rmapping = A->rmap->mapping;
2249   }
2250   if (cmapping) {
2251     PetscValidPointer(cmapping, 3);
2252     *cmapping = A->cmap->mapping;
2253   }
2254   PetscFunctionReturn(PETSC_SUCCESS);
2255 }
2256 
2257 /*@
2258    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2259 
2260    Logically Collective
2261 
2262    Input Parameters:
2263 +  A - the matrix
2264 . rmap - row layout
2265 - cmap - column layout
2266 
2267    Level: advanced
2268 
2269    Note:
2270    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2271 
2272 .seealso: `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2273 @*/
2274 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2275 {
2276   PetscFunctionBegin;
2277   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2278   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2279   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2280   PetscFunctionReturn(PETSC_SUCCESS);
2281 }
2282 
2283 /*@
2284    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2285 
2286    Not Collective
2287 
2288    Input Parameter:
2289 .  A - the matrix
2290 
2291    Output Parameters:
2292 + rmap - row layout
2293 - cmap - column layout
2294 
2295    Level: advanced
2296 
2297 .seealso: `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2298 @*/
2299 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2300 {
2301   PetscFunctionBegin;
2302   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2303   PetscValidType(A, 1);
2304   if (rmap) {
2305     PetscValidPointer(rmap, 2);
2306     *rmap = A->rmap;
2307   }
2308   if (cmap) {
2309     PetscValidPointer(cmap, 3);
2310     *cmap = A->cmap;
2311   }
2312   PetscFunctionReturn(PETSC_SUCCESS);
2313 }
2314 
2315 /*@C
2316    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2317    using a local numbering of the nodes.
2318 
2319    Not Collective
2320 
2321    Input Parameters:
2322 +  mat - the matrix
2323 .  nrow - number of rows
2324 .  irow - the row local indices
2325 .  ncol - number of columns
2326 .  icol - the column local indices
2327 .  y -  a logically two-dimensional array of values
2328 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2329 
2330    Level: intermediate
2331 
2332    Notes:
2333    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2334       `MatSetUp()` before using this routine
2335 
2336    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2337 
2338    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2339    options cannot be mixed without intervening calls to the assembly
2340    routines.
2341 
2342    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2343    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2344 
2345    Developer Note:
2346     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2347                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2348 
2349 .seealso: `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2350           `MatGetValuesLocal()`
2351 @*/
2352 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2353 {
2354   PetscFunctionBeginHot;
2355   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2356   PetscValidType(mat, 1);
2357   MatCheckPreallocated(mat, 1);
2358   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2359   PetscValidIntPointer(irow, 3);
2360   PetscValidIntPointer(icol, 5);
2361   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2362   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2363   if (PetscDefined(USE_DEBUG)) {
2364     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2365     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2366   }
2367 
2368   if (mat->assembled) {
2369     mat->was_assembled = PETSC_TRUE;
2370     mat->assembled     = PETSC_FALSE;
2371   }
2372   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2373   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2374   else {
2375     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2376     const PetscInt *irowm, *icolm;
2377 
2378     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2379       bufr  = buf;
2380       bufc  = buf + nrow;
2381       irowm = bufr;
2382       icolm = bufc;
2383     } else {
2384       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2385       irowm = bufr;
2386       icolm = bufc;
2387     }
2388     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2389     else irowm = irow;
2390     if (mat->cmap->mapping) {
2391       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2392         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2393       } else icolm = irowm;
2394     } else icolm = icol;
2395     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2396     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2397   }
2398   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2399   PetscFunctionReturn(PETSC_SUCCESS);
2400 }
2401 
2402 /*@C
2403    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2404    using a local ordering of the nodes a block at a time.
2405 
2406    Not Collective
2407 
2408    Input Parameters:
2409 +  x - the matrix
2410 .  nrow - number of rows
2411 .  irow - the row local indices
2412 .  ncol - number of columns
2413 .  icol - the column local indices
2414 .  y -  a logically two-dimensional array of values
2415 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2416 
2417    Level: intermediate
2418 
2419    Notes:
2420    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2421       `MatSetUp()` before using this routine
2422 
2423    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2424       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2425 
2426    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2427    options cannot be mixed without intervening calls to the assembly
2428    routines.
2429 
2430    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2431    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2432 
2433    Developer Note:
2434     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2435                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2436 
2437 .seealso: `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2438           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2439 @*/
2440 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2441 {
2442   PetscFunctionBeginHot;
2443   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2444   PetscValidType(mat, 1);
2445   MatCheckPreallocated(mat, 1);
2446   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2447   PetscValidIntPointer(irow, 3);
2448   PetscValidIntPointer(icol, 5);
2449   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2450   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2451   if (PetscDefined(USE_DEBUG)) {
2452     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2453     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);
2454   }
2455 
2456   if (mat->assembled) {
2457     mat->was_assembled = PETSC_TRUE;
2458     mat->assembled     = PETSC_FALSE;
2459   }
2460   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2461     PetscInt irbs, rbs;
2462     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2463     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2464     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2465   }
2466   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2467     PetscInt icbs, cbs;
2468     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2469     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2470     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2471   }
2472   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2473   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2474   else {
2475     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2476     const PetscInt *irowm, *icolm;
2477 
2478     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2479       bufr  = buf;
2480       bufc  = buf + nrow;
2481       irowm = bufr;
2482       icolm = bufc;
2483     } else {
2484       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2485       irowm = bufr;
2486       icolm = bufc;
2487     }
2488     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2489     else irowm = irow;
2490     if (mat->cmap->mapping) {
2491       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2492         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2493       } else icolm = irowm;
2494     } else icolm = icol;
2495     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2496     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2497   }
2498   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2499   PetscFunctionReturn(PETSC_SUCCESS);
2500 }
2501 
2502 /*@
2503    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2504 
2505    Collective
2506 
2507    Input Parameters:
2508 +  mat - the matrix
2509 -  x   - the vector to be multiplied
2510 
2511    Output Parameters:
2512 .  y - the result
2513 
2514    Level: developer
2515 
2516    Note:
2517    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2518    call `MatMultDiagonalBlock`(A,y,y).
2519 
2520 .seealso: `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2521 @*/
2522 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2523 {
2524   PetscFunctionBegin;
2525   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2526   PetscValidType(mat, 1);
2527   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2528   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2529 
2530   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2531   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2532   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2533   MatCheckPreallocated(mat, 1);
2534 
2535   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2536   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2537   PetscFunctionReturn(PETSC_SUCCESS);
2538 }
2539 
2540 /*@
2541    MatMult - Computes the matrix-vector product, y = Ax.
2542 
2543    Neighbor-wise Collective
2544 
2545    Input Parameters:
2546 +  mat - the matrix
2547 -  x   - the vector to be multiplied
2548 
2549    Output Parameters:
2550 .  y - the result
2551 
2552    Level: beginner
2553 
2554    Note:
2555    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2556    call `MatMult`(A,y,y).
2557 
2558 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2559 @*/
2560 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2561 {
2562   PetscFunctionBegin;
2563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2564   PetscValidType(mat, 1);
2565   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2566   VecCheckAssembled(x);
2567   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2568   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2569   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2570   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2571   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);
2572   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);
2573   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);
2574   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);
2575   PetscCall(VecSetErrorIfLocked(y, 3));
2576   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2577   MatCheckPreallocated(mat, 1);
2578 
2579   PetscCall(VecLockReadPush(x));
2580   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2581   PetscUseTypeMethod(mat, mult, x, y);
2582   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2583   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2584   PetscCall(VecLockReadPop(x));
2585   PetscFunctionReturn(PETSC_SUCCESS);
2586 }
2587 
2588 /*@
2589    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2590 
2591    Neighbor-wise Collective
2592 
2593    Input Parameters:
2594 +  mat - the matrix
2595 -  x   - the vector to be multiplied
2596 
2597    Output Parameters:
2598 .  y - the result
2599 
2600    Level: beginner
2601 
2602    Notes:
2603    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2604    call `MatMultTranspose`(A,y,y).
2605 
2606    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2607    use `MatMultHermitianTranspose()`
2608 
2609 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2610 @*/
2611 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2612 {
2613   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2614 
2615   PetscFunctionBegin;
2616   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2617   PetscValidType(mat, 1);
2618   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2619   VecCheckAssembled(x);
2620   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2621 
2622   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2623   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2624   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2625   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);
2626   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);
2627   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);
2628   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);
2629   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2630   MatCheckPreallocated(mat, 1);
2631 
2632   if (!mat->ops->multtranspose) {
2633     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2634     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);
2635   } else op = mat->ops->multtranspose;
2636   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2637   PetscCall(VecLockReadPush(x));
2638   PetscCall((*op)(mat, x, y));
2639   PetscCall(VecLockReadPop(x));
2640   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2641   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2642   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2643   PetscFunctionReturn(PETSC_SUCCESS);
2644 }
2645 
2646 /*@
2647    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2648 
2649    Neighbor-wise Collective
2650 
2651    Input Parameters:
2652 +  mat - the matrix
2653 -  x   - the vector to be multilplied
2654 
2655    Output Parameters:
2656 .  y - the result
2657 
2658    Level: beginner
2659 
2660    Notes:
2661    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2662    call `MatMultHermitianTranspose`(A,y,y).
2663 
2664    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2665 
2666    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2667 
2668 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2669 @*/
2670 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2671 {
2672   PetscFunctionBegin;
2673   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2674   PetscValidType(mat, 1);
2675   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2676   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2677 
2678   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2679   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2680   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2681   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);
2682   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);
2683   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);
2684   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);
2685   MatCheckPreallocated(mat, 1);
2686 
2687   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2688 #if defined(PETSC_USE_COMPLEX)
2689   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2690     PetscCall(VecLockReadPush(x));
2691     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2692     else PetscUseTypeMethod(mat, mult, x, y);
2693     PetscCall(VecLockReadPop(x));
2694   } else {
2695     Vec w;
2696     PetscCall(VecDuplicate(x, &w));
2697     PetscCall(VecCopy(x, w));
2698     PetscCall(VecConjugate(w));
2699     PetscCall(MatMultTranspose(mat, w, y));
2700     PetscCall(VecDestroy(&w));
2701     PetscCall(VecConjugate(y));
2702   }
2703   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2704 #else
2705   PetscCall(MatMultTranspose(mat, x, y));
2706 #endif
2707   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2708   PetscFunctionReturn(PETSC_SUCCESS);
2709 }
2710 
2711 /*@
2712     MatMultAdd -  Computes v3 = v2 + A * v1.
2713 
2714     Neighbor-wise Collective
2715 
2716     Input Parameters:
2717 +   mat - the matrix
2718 -   v1, v2 - the vectors
2719 
2720     Output Parameters:
2721 .   v3 - the result
2722 
2723     Level: beginner
2724 
2725     Note:
2726     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2727     call `MatMultAdd`(A,v1,v2,v1).
2728 
2729 .seealso: `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2730 @*/
2731 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2732 {
2733   PetscFunctionBegin;
2734   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2735   PetscValidType(mat, 1);
2736   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2737   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2738   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2739 
2740   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2741   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2742   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);
2743   /* 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);
2744      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); */
2745   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);
2746   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);
2747   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2748   MatCheckPreallocated(mat, 1);
2749 
2750   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2751   PetscCall(VecLockReadPush(v1));
2752   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2753   PetscCall(VecLockReadPop(v1));
2754   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2755   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2756   PetscFunctionReturn(PETSC_SUCCESS);
2757 }
2758 
2759 /*@
2760    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2761 
2762    Neighbor-wise Collective
2763 
2764    Input Parameters:
2765 +  mat - the matrix
2766 -  v1, v2 - the vectors
2767 
2768    Output Parameters:
2769 .  v3 - the result
2770 
2771    Level: beginner
2772 
2773    Note:
2774    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2775    call `MatMultTransposeAdd`(A,v1,v2,v1).
2776 
2777 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2778 @*/
2779 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2780 {
2781   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2782 
2783   PetscFunctionBegin;
2784   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2785   PetscValidType(mat, 1);
2786   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2787   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2788   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2789 
2790   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2791   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2792   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);
2793   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);
2794   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);
2795   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2796   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2797   MatCheckPreallocated(mat, 1);
2798 
2799   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2800   PetscCall(VecLockReadPush(v1));
2801   PetscCall((*op)(mat, v1, v2, v3));
2802   PetscCall(VecLockReadPop(v1));
2803   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2804   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2805   PetscFunctionReturn(PETSC_SUCCESS);
2806 }
2807 
2808 /*@
2809    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2810 
2811    Neighbor-wise Collective
2812 
2813    Input Parameters:
2814 +  mat - the matrix
2815 -  v1, v2 - the vectors
2816 
2817    Output Parameters:
2818 .  v3 - the result
2819 
2820    Level: beginner
2821 
2822    Note:
2823    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2824    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2825 
2826 .seealso: `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2827 @*/
2828 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2829 {
2830   PetscFunctionBegin;
2831   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2832   PetscValidType(mat, 1);
2833   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2834   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2835   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2836 
2837   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2838   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2839   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2840   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);
2841   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);
2842   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);
2843   MatCheckPreallocated(mat, 1);
2844 
2845   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2846   PetscCall(VecLockReadPush(v1));
2847   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2848   else {
2849     Vec w, z;
2850     PetscCall(VecDuplicate(v1, &w));
2851     PetscCall(VecCopy(v1, w));
2852     PetscCall(VecConjugate(w));
2853     PetscCall(VecDuplicate(v3, &z));
2854     PetscCall(MatMultTranspose(mat, w, z));
2855     PetscCall(VecDestroy(&w));
2856     PetscCall(VecConjugate(z));
2857     if (v2 != v3) {
2858       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2859     } else {
2860       PetscCall(VecAXPY(v3, 1.0, z));
2861     }
2862     PetscCall(VecDestroy(&z));
2863   }
2864   PetscCall(VecLockReadPop(v1));
2865   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2866   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2867   PetscFunctionReturn(PETSC_SUCCESS);
2868 }
2869 
2870 /*@C
2871    MatGetFactorType - gets the type of factorization it is
2872 
2873    Not Collective
2874 
2875    Input Parameters:
2876 .  mat - the matrix
2877 
2878    Output Parameters:
2879 .  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`
2880 
2881    Level: intermediate
2882 
2883 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2884           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2885 @*/
2886 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2887 {
2888   PetscFunctionBegin;
2889   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2890   PetscValidType(mat, 1);
2891   PetscValidPointer(t, 2);
2892   *t = mat->factortype;
2893   PetscFunctionReturn(PETSC_SUCCESS);
2894 }
2895 
2896 /*@C
2897    MatSetFactorType - sets the type of factorization it is
2898 
2899    Logically Collective
2900 
2901    Input Parameters:
2902 +  mat - the matrix
2903 -  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`
2904 
2905    Level: intermediate
2906 
2907 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2908           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2909 @*/
2910 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2911 {
2912   PetscFunctionBegin;
2913   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2914   PetscValidType(mat, 1);
2915   mat->factortype = t;
2916   PetscFunctionReturn(PETSC_SUCCESS);
2917 }
2918 
2919 /*@C
2920    MatGetInfo - Returns information about matrix storage (number of
2921    nonzeros, memory, etc.).
2922 
2923    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2924 
2925    Input Parameters:
2926 +  mat - the matrix
2927 -  flag - flag indicating the type of parameters to be returned (`MAT_LOCAL` - local matrix, `MAT_GLOBAL_MAX` - maximum over all processors, `MAT_GLOBAL_SUM` - sum over all processors)
2928 
2929    Output Parameters:
2930 .  info - matrix information context
2931 
2932    Notes:
2933    The `MatInfo` context contains a variety of matrix data, including
2934    number of nonzeros allocated and used, number of mallocs during
2935    matrix assembly, etc.  Additional information for factored matrices
2936    is provided (such as the fill ratio, number of mallocs during
2937    factorization, etc.).  Much of this info is printed to `PETSC_STDOUT`
2938    when using the runtime options
2939 $       -info -mat_view ::ascii_info
2940 
2941    Example:
2942    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2943    data within the MatInfo context.  For example,
2944 .vb
2945       MatInfo info;
2946       Mat     A;
2947       double  mal, nz_a, nz_u;
2948 
2949       MatGetInfo(A,MAT_LOCAL,&info);
2950       mal  = info.mallocs;
2951       nz_a = info.nz_allocated;
2952 .ve
2953 
2954    Fortran users should declare info as a double precision
2955    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2956    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2957    a complete list of parameter names.
2958 .vb
2959       double  precision info(MAT_INFO_SIZE)
2960       double  precision mal, nz_a
2961       Mat     A
2962       integer ierr
2963 
2964       call MatGetInfo(A,MAT_LOCAL,info,ierr)
2965       mal = info(MAT_INFO_MALLOCS)
2966       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2967 .ve
2968 
2969     Level: intermediate
2970 
2971     Developer Note:
2972     The Fortran interface is not autogenerated as the
2973     interface definition cannot be generated correctly [due to `MatInfo` argument]
2974 
2975 .seealso: `Mat`, `MatInfo`, `MatStashGetInfo()`
2976 @*/
2977 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2978 {
2979   PetscFunctionBegin;
2980   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2981   PetscValidType(mat, 1);
2982   PetscValidPointer(info, 3);
2983   MatCheckPreallocated(mat, 1);
2984   PetscUseTypeMethod(mat, getinfo, flag, info);
2985   PetscFunctionReturn(PETSC_SUCCESS);
2986 }
2987 
2988 /*
2989    This is used by external packages where it is not easy to get the info from the actual
2990    matrix factorization.
2991 */
2992 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2993 {
2994   PetscFunctionBegin;
2995   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2996   PetscFunctionReturn(PETSC_SUCCESS);
2997 }
2998 
2999 /*@C
3000    MatLUFactor - Performs in-place LU factorization of matrix.
3001 
3002    Collective
3003 
3004    Input Parameters:
3005 +  mat - the matrix
3006 .  row - row permutation
3007 .  col - column permutation
3008 -  info - options for factorization, includes
3009 .vb
3010           fill - expected fill as ratio of original fill.
3011           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3012                    Run with the option -info to determine an optimal value to use
3013 .ve
3014    Level: developer
3015 
3016    Notes:
3017    Most users should employ the `KSP` interface for linear solvers
3018    instead of working directly with matrix algebra routines such as this.
3019    See, e.g., `KSPCreate()`.
3020 
3021    This changes the state of the matrix to a factored matrix; it cannot be used
3022    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3023 
3024    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3025    when not using `KSP`.
3026 
3027    Developer Note:
3028    The Fortran interface is not autogenerated as the
3029    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3030 
3031 .seealso: [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3032           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3033 @*/
3034 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3035 {
3036   MatFactorInfo tinfo;
3037 
3038   PetscFunctionBegin;
3039   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3040   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3041   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3042   if (info) PetscValidPointer(info, 4);
3043   PetscValidType(mat, 1);
3044   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3045   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3046   MatCheckPreallocated(mat, 1);
3047   if (!info) {
3048     PetscCall(MatFactorInfoInitialize(&tinfo));
3049     info = &tinfo;
3050   }
3051 
3052   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3053   PetscUseTypeMethod(mat, lufactor, row, col, info);
3054   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3055   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3056   PetscFunctionReturn(PETSC_SUCCESS);
3057 }
3058 
3059 /*@C
3060    MatILUFactor - Performs in-place ILU factorization of matrix.
3061 
3062    Collective
3063 
3064    Input Parameters:
3065 +  mat - the matrix
3066 .  row - row permutation
3067 .  col - column permutation
3068 -  info - structure containing
3069 .vb
3070       levels - number of levels of fill.
3071       expected fill - as ratio of original fill.
3072       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3073                 missing diagonal entries)
3074 .ve
3075 
3076    Level: developer
3077 
3078    Notes:
3079    Most users should employ the `KSP` interface for linear solvers
3080    instead of working directly with matrix algebra routines such as this.
3081    See, e.g., `KSPCreate()`.
3082 
3083    Probably really in-place only when level of fill is zero, otherwise allocates
3084    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3085    when not using `KSP`.
3086 
3087    Developer Note:
3088    The Fortran interface is not autogenerated as the
3089    interface definition cannot be generated correctly [due to MatFactorInfo]
3090 
3091 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3092 @*/
3093 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3094 {
3095   PetscFunctionBegin;
3096   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3097   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3098   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3099   PetscValidPointer(info, 4);
3100   PetscValidType(mat, 1);
3101   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3102   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3103   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3104   MatCheckPreallocated(mat, 1);
3105 
3106   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3107   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3108   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3109   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3110   PetscFunctionReturn(PETSC_SUCCESS);
3111 }
3112 
3113 /*@C
3114    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3115    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3116 
3117    Collective on fact
3118 
3119    Input Parameters:
3120 +  fact - the factor matrix obtained with `MatGetFactor()`
3121 .  mat - the matrix
3122 .  row, col - row and column permutations
3123 -  info - options for factorization, includes
3124 .vb
3125           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3126           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3127 .ve
3128 
3129    Level: developer
3130 
3131    Notes:
3132     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3133 
3134    Most users should employ the simplified `KSP` interface for linear solvers
3135    instead of working directly with matrix algebra routines such as this.
3136    See, e.g., `KSPCreate()`.
3137 
3138    Developer Note:
3139    The Fortran interface is not autogenerated as the
3140    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3141 
3142 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3143 @*/
3144 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3145 {
3146   MatFactorInfo tinfo;
3147 
3148   PetscFunctionBegin;
3149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3150   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3151   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3152   if (info) PetscValidPointer(info, 5);
3153   PetscValidType(mat, 2);
3154   PetscValidPointer(fact, 1);
3155   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3156   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3157   if (!(fact)->ops->lufactorsymbolic) {
3158     MatSolverType stype;
3159     PetscCall(MatFactorGetSolverType(fact, &stype));
3160     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic LU using solver package %s", ((PetscObject)mat)->type_name, stype);
3161   }
3162   MatCheckPreallocated(mat, 2);
3163   if (!info) {
3164     PetscCall(MatFactorInfoInitialize(&tinfo));
3165     info = &tinfo;
3166   }
3167 
3168   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3169   PetscCall((fact->ops->lufactorsymbolic)(fact, mat, row, col, info));
3170   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3171   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3172   PetscFunctionReturn(PETSC_SUCCESS);
3173 }
3174 
3175 /*@C
3176    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3177    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3178 
3179    Collective on fact
3180 
3181    Input Parameters:
3182 +  fact - the factor matrix obtained with `MatGetFactor()`
3183 .  mat - the matrix
3184 -  info - options for factorization
3185 
3186    Level: developer
3187 
3188    Notes:
3189    See `MatLUFactor()` for in-place factorization.  See
3190    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3191 
3192    Most users should employ the `KSP` interface for linear solvers
3193    instead of working directly with matrix algebra routines such as this.
3194    See, e.g., `KSPCreate()`.
3195 
3196     Developer Note:
3197     The Fortran interface is not autogenerated as the
3198     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3199 
3200 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3201 @*/
3202 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3203 {
3204   MatFactorInfo tinfo;
3205 
3206   PetscFunctionBegin;
3207   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3208   PetscValidType(mat, 2);
3209   PetscValidPointer(fact, 1);
3210   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3211   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3212   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,
3213              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3214 
3215   PetscCheck((fact)->ops->lufactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric LU", ((PetscObject)mat)->type_name);
3216   MatCheckPreallocated(mat, 2);
3217   if (!info) {
3218     PetscCall(MatFactorInfoInitialize(&tinfo));
3219     info = &tinfo;
3220   }
3221 
3222   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3223   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3224   PetscCall((fact->ops->lufactornumeric)(fact, mat, info));
3225   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3226   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3227   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3228   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3229   PetscFunctionReturn(PETSC_SUCCESS);
3230 }
3231 
3232 /*@C
3233    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3234    symmetric matrix.
3235 
3236    Collective
3237 
3238    Input Parameters:
3239 +  mat - the matrix
3240 .  perm - row and column permutations
3241 -  f - expected fill as ratio of original fill
3242 
3243    Level: developer
3244 
3245    Notes:
3246    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3247    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3248 
3249    Most users should employ the `KSP` interface for linear solvers
3250    instead of working directly with matrix algebra routines such as this.
3251    See, e.g., `KSPCreate()`.
3252 
3253    Developer Note:
3254    The Fortran interface is not autogenerated as the
3255    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3256 
3257 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3258           `MatGetOrdering()`
3259 @*/
3260 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3261 {
3262   MatFactorInfo tinfo;
3263 
3264   PetscFunctionBegin;
3265   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3266   PetscValidType(mat, 1);
3267   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3268   if (info) PetscValidPointer(info, 3);
3269   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3270   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3271   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3272   MatCheckPreallocated(mat, 1);
3273   if (!info) {
3274     PetscCall(MatFactorInfoInitialize(&tinfo));
3275     info = &tinfo;
3276   }
3277 
3278   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3279   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3280   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3281   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3282   PetscFunctionReturn(PETSC_SUCCESS);
3283 }
3284 
3285 /*@C
3286    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3287    of a symmetric matrix.
3288 
3289    Collective on fact
3290 
3291    Input Parameters:
3292 +  fact - the factor matrix obtained with `MatGetFactor()`
3293 .  mat - the matrix
3294 .  perm - row and column permutations
3295 -  info - options for factorization, includes
3296 .vb
3297           fill - expected fill as ratio of original fill.
3298           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3299                    Run with the option -info to determine an optimal value to use
3300 .ve
3301 
3302    Level: developer
3303 
3304    Notes:
3305    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3306    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3307 
3308    Most users should employ the `KSP` interface for linear solvers
3309    instead of working directly with matrix algebra routines such as this.
3310    See, e.g., `KSPCreate()`.
3311 
3312    Developer Note:
3313    The Fortran interface is not autogenerated as the
3314    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3315 
3316 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3317           `MatGetOrdering()`
3318 @*/
3319 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3320 {
3321   MatFactorInfo tinfo;
3322 
3323   PetscFunctionBegin;
3324   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3325   PetscValidType(mat, 2);
3326   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3327   if (info) PetscValidPointer(info, 4);
3328   PetscValidPointer(fact, 1);
3329   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3330   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3331   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3332   if (!(fact)->ops->choleskyfactorsymbolic) {
3333     MatSolverType stype;
3334     PetscCall(MatFactorGetSolverType(fact, &stype));
3335     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s symbolic factor Cholesky using solver package %s", ((PetscObject)mat)->type_name, stype);
3336   }
3337   MatCheckPreallocated(mat, 2);
3338   if (!info) {
3339     PetscCall(MatFactorInfoInitialize(&tinfo));
3340     info = &tinfo;
3341   }
3342 
3343   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3344   PetscCall((fact->ops->choleskyfactorsymbolic)(fact, mat, perm, info));
3345   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3346   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3347   PetscFunctionReturn(PETSC_SUCCESS);
3348 }
3349 
3350 /*@C
3351    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3352    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3353    `MatCholeskyFactorSymbolic()`.
3354 
3355    Collective on fact
3356 
3357    Input Parameters:
3358 +  fact - the factor matrix obtained with `MatGetFactor()`
3359 .  mat - the initial matrix
3360 .  info - options for factorization
3361 -  fact - the symbolic factor of mat
3362 
3363    Level: developer
3364 
3365    Note:
3366    Most users should employ the `KSP` interface for linear solvers
3367    instead of working directly with matrix algebra routines such as this.
3368    See, e.g., `KSPCreate()`.
3369 
3370    Developer Note:
3371    The Fortran interface is not autogenerated as the
3372    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3373 
3374 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3375 @*/
3376 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3377 {
3378   MatFactorInfo tinfo;
3379 
3380   PetscFunctionBegin;
3381   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3382   PetscValidType(mat, 2);
3383   PetscValidPointer(fact, 1);
3384   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3385   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3386   PetscCheck((fact)->ops->choleskyfactornumeric, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s numeric factor Cholesky", ((PetscObject)mat)->type_name);
3387   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,
3388              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3389   MatCheckPreallocated(mat, 2);
3390   if (!info) {
3391     PetscCall(MatFactorInfoInitialize(&tinfo));
3392     info = &tinfo;
3393   }
3394 
3395   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3396   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3397   PetscCall((fact->ops->choleskyfactornumeric)(fact, mat, info));
3398   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3399   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3400   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3401   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3402   PetscFunctionReturn(PETSC_SUCCESS);
3403 }
3404 
3405 /*@
3406    MatQRFactor - Performs in-place QR factorization of matrix.
3407 
3408    Collective
3409 
3410    Input Parameters:
3411 +  mat - the matrix
3412 .  col - column permutation
3413 -  info - options for factorization, includes
3414 .vb
3415           fill - expected fill as ratio of original fill.
3416           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3417                    Run with the option -info to determine an optimal value to use
3418 .ve
3419 
3420    Level: developer
3421 
3422    Notes:
3423    Most users should employ the `KSP` interface for linear solvers
3424    instead of working directly with matrix algebra routines such as this.
3425    See, e.g., `KSPCreate()`.
3426 
3427    This changes the state of the matrix to a factored matrix; it cannot be used
3428    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3429 
3430    Developer Note:
3431    The Fortran interface is not autogenerated as the
3432    interface definition cannot be generated correctly [due to MatFactorInfo]
3433 
3434 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3435           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3436 @*/
3437 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3438 {
3439   PetscFunctionBegin;
3440   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3441   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3442   if (info) PetscValidPointer(info, 3);
3443   PetscValidType(mat, 1);
3444   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3445   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3446   MatCheckPreallocated(mat, 1);
3447   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3448   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3449   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3450   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3451   PetscFunctionReturn(PETSC_SUCCESS);
3452 }
3453 
3454 /*@
3455    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3456    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3457 
3458    Collective on fact
3459 
3460    Input Parameters:
3461 +  fact - the factor matrix obtained with `MatGetFactor()`
3462 .  mat - the matrix
3463 .  col - column permutation
3464 -  info - options for factorization, includes
3465 .vb
3466           fill - expected fill as ratio of original fill.
3467           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3468                    Run with the option -info to determine an optimal value to use
3469 .ve
3470 
3471    Level: developer
3472 
3473    Note:
3474    Most users should employ the `KSP` interface for linear solvers
3475    instead of working directly with matrix algebra routines such as this.
3476    See, e.g., `KSPCreate()`.
3477 
3478    Developer Note:
3479    The Fortran interface is not autogenerated as the
3480    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3481 
3482 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3483 @*/
3484 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3485 {
3486   MatFactorInfo tinfo;
3487 
3488   PetscFunctionBegin;
3489   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3490   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3491   if (info) PetscValidPointer(info, 4);
3492   PetscValidType(mat, 2);
3493   PetscValidPointer(fact, 1);
3494   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3495   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3496   MatCheckPreallocated(mat, 2);
3497   if (!info) {
3498     PetscCall(MatFactorInfoInitialize(&tinfo));
3499     info = &tinfo;
3500   }
3501 
3502   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3503   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3504   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3505   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3506   PetscFunctionReturn(PETSC_SUCCESS);
3507 }
3508 
3509 /*@
3510    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3511    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3512 
3513    Collective on fact
3514 
3515    Input Parameters:
3516 +  fact - the factor matrix obtained with `MatGetFactor()`
3517 .  mat - the matrix
3518 -  info - options for factorization
3519 
3520    Level: developer
3521 
3522    Notes:
3523    See `MatQRFactor()` for in-place factorization.
3524 
3525    Most users should employ the `KSP` interface for linear solvers
3526    instead of working directly with matrix algebra routines such as this.
3527    See, e.g., `KSPCreate()`.
3528 
3529    Developer Note:
3530    The Fortran interface is not autogenerated as the
3531    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3532 
3533 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3534 @*/
3535 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3536 {
3537   MatFactorInfo tinfo;
3538 
3539   PetscFunctionBegin;
3540   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3541   PetscValidType(mat, 2);
3542   PetscValidPointer(fact, 1);
3543   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3544   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3545   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,
3546              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3547 
3548   MatCheckPreallocated(mat, 2);
3549   if (!info) {
3550     PetscCall(MatFactorInfoInitialize(&tinfo));
3551     info = &tinfo;
3552   }
3553 
3554   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3555   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3556   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3557   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3558   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3559   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3560   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3561   PetscFunctionReturn(PETSC_SUCCESS);
3562 }
3563 
3564 /*@
3565    MatSolve - Solves A x = b, given a factored matrix.
3566 
3567    Neighbor-wise Collective
3568 
3569    Input Parameters:
3570 +  mat - the factored matrix
3571 -  b - the right-hand-side vector
3572 
3573    Output Parameter:
3574 .  x - the result vector
3575 
3576    Level: developer
3577 
3578    Notes:
3579    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3580    call `MatSolve`(A,x,x).
3581 
3582    Most users should employ the `KSP` interface for linear solvers
3583    instead of working directly with matrix algebra routines such as this.
3584    See, e.g., `KSPCreate()`.
3585 
3586 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3587 @*/
3588 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3589 {
3590   PetscFunctionBegin;
3591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3592   PetscValidType(mat, 1);
3593   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3594   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3595   PetscCheckSameComm(mat, 1, b, 2);
3596   PetscCheckSameComm(mat, 1, x, 3);
3597   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3598   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);
3599   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);
3600   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);
3601   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3602   MatCheckPreallocated(mat, 1);
3603 
3604   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3605   if (mat->factorerrortype) {
3606     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3607     PetscCall(VecSetInf(x));
3608   } else PetscUseTypeMethod(mat, solve, b, x);
3609   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3610   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3611   PetscFunctionReturn(PETSC_SUCCESS);
3612 }
3613 
3614 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3615 {
3616   Vec      b, x;
3617   PetscInt N, i;
3618   PetscErrorCode (*f)(Mat, Vec, Vec);
3619   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3620 
3621   PetscFunctionBegin;
3622   if (A->factorerrortype) {
3623     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3624     PetscCall(MatSetInf(X));
3625     PetscFunctionReturn(PETSC_SUCCESS);
3626   }
3627   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3628   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3629   PetscCall(MatBoundToCPU(A, &Abound));
3630   if (!Abound) {
3631     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3632     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3633   }
3634 #if defined(PETSC_HAVE_CUDA)
3635   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3636   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3637 #elif (PETSC_HAVE_HIP)
3638   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3639   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3640 #endif
3641   PetscCall(MatGetSize(B, NULL, &N));
3642   for (i = 0; i < N; i++) {
3643     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3644     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3645     PetscCall((*f)(A, b, x));
3646     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3647     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3648   }
3649   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3650   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3651   PetscFunctionReturn(PETSC_SUCCESS);
3652 }
3653 
3654 /*@
3655    MatMatSolve - Solves A X = B, given a factored matrix.
3656 
3657    Neighbor-wise Collective
3658 
3659    Input Parameters:
3660 +  A - the factored matrix
3661 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3662 
3663    Output Parameter:
3664 .  X - the result matrix (dense matrix)
3665 
3666    Level: developer
3667 
3668    Note:
3669    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3670    otherwise, `B` and `X` cannot be the same.
3671 
3672 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3673 @*/
3674 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3675 {
3676   PetscFunctionBegin;
3677   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3678   PetscValidType(A, 1);
3679   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3680   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3681   PetscCheckSameComm(A, 1, B, 2);
3682   PetscCheckSameComm(A, 1, X, 3);
3683   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);
3684   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);
3685   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");
3686   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3687   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3688   MatCheckPreallocated(A, 1);
3689 
3690   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3691   if (!A->ops->matsolve) {
3692     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3693     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3694   } else PetscUseTypeMethod(A, matsolve, B, X);
3695   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3696   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3697   PetscFunctionReturn(PETSC_SUCCESS);
3698 }
3699 
3700 /*@
3701    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3702 
3703    Neighbor-wise Collective
3704 
3705    Input Parameters:
3706 +  A - the factored matrix
3707 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3708 
3709    Output Parameter:
3710 .  X - the result matrix (dense matrix)
3711 
3712    Level: developer
3713 
3714    Note:
3715    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3716    call `MatMatSolveTranspose`(A,X,X).
3717 
3718 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3719 @*/
3720 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3721 {
3722   PetscFunctionBegin;
3723   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3724   PetscValidType(A, 1);
3725   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3726   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3727   PetscCheckSameComm(A, 1, B, 2);
3728   PetscCheckSameComm(A, 1, X, 3);
3729   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3730   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);
3731   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);
3732   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);
3733   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");
3734   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3735   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3736   MatCheckPreallocated(A, 1);
3737 
3738   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3739   if (!A->ops->matsolvetranspose) {
3740     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3741     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3742   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3743   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3744   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3745   PetscFunctionReturn(PETSC_SUCCESS);
3746 }
3747 
3748 /*@
3749    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3750 
3751    Neighbor-wise Collective
3752 
3753    Input Parameters:
3754 +  A - the factored matrix
3755 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3756 
3757    Output Parameter:
3758 .  X - the result matrix (dense matrix)
3759 
3760    Level: developer
3761 
3762    Note:
3763    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
3764    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3765 
3766 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3767 @*/
3768 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3769 {
3770   PetscFunctionBegin;
3771   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3772   PetscValidType(A, 1);
3773   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3774   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3775   PetscCheckSameComm(A, 1, Bt, 2);
3776   PetscCheckSameComm(A, 1, X, 3);
3777 
3778   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3779   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);
3780   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);
3781   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");
3782   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3783   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3784   MatCheckPreallocated(A, 1);
3785 
3786   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3787   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3788   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3789   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3790   PetscFunctionReturn(PETSC_SUCCESS);
3791 }
3792 
3793 /*@
3794    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3795                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3796 
3797    Neighbor-wise Collective
3798 
3799    Input Parameters:
3800 +  mat - the factored matrix
3801 -  b - the right-hand-side vector
3802 
3803    Output Parameter:
3804 .  x - the result vector
3805 
3806    Level: developer
3807 
3808    Notes:
3809    `MatSolve()` should be used for most applications, as it performs
3810    a forward solve followed by a backward solve.
3811 
3812    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3813    call `MatForwardSolve`(A,x,x).
3814 
3815    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3816    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3817    `MatForwardSolve()` solves U^T*D y = b, and
3818    `MatBackwardSolve()` solves U x = y.
3819    Thus they do not provide a symmetric preconditioner.
3820 
3821 .seealso: `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3822 @*/
3823 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3824 {
3825   PetscFunctionBegin;
3826   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3827   PetscValidType(mat, 1);
3828   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3829   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3830   PetscCheckSameComm(mat, 1, b, 2);
3831   PetscCheckSameComm(mat, 1, x, 3);
3832   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3833   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);
3834   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);
3835   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);
3836   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3837   MatCheckPreallocated(mat, 1);
3838 
3839   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3840   PetscUseTypeMethod(mat, forwardsolve, b, x);
3841   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3842   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3843   PetscFunctionReturn(PETSC_SUCCESS);
3844 }
3845 
3846 /*@
3847    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3848                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3849 
3850    Neighbor-wise Collective
3851 
3852    Input Parameters:
3853 +  mat - the factored matrix
3854 -  b - the right-hand-side vector
3855 
3856    Output Parameter:
3857 .  x - the result vector
3858 
3859    Level: developer
3860 
3861    Notes:
3862    `MatSolve()` should be used for most applications, as it performs
3863    a forward solve followed by a backward solve.
3864 
3865    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3866    call `MatBackwardSolve`(A,x,x).
3867 
3868    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3869    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3870    `MatForwardSolve()` solves U^T*D y = b, and
3871    `MatBackwardSolve()` solves U x = y.
3872    Thus they do not provide a symmetric preconditioner.
3873 
3874 .seealso: `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3875 @*/
3876 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3877 {
3878   PetscFunctionBegin;
3879   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3880   PetscValidType(mat, 1);
3881   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3882   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3883   PetscCheckSameComm(mat, 1, b, 2);
3884   PetscCheckSameComm(mat, 1, x, 3);
3885   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3886   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);
3887   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);
3888   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);
3889   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3890   MatCheckPreallocated(mat, 1);
3891 
3892   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3893   PetscUseTypeMethod(mat, backwardsolve, b, x);
3894   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3895   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3896   PetscFunctionReturn(PETSC_SUCCESS);
3897 }
3898 
3899 /*@
3900    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3901 
3902    Neighbor-wise Collective
3903 
3904    Input Parameters:
3905 +  mat - the factored matrix
3906 .  b - the right-hand-side vector
3907 -  y - the vector to be added to
3908 
3909    Output Parameter:
3910 .  x - the result vector
3911 
3912    Level: developer
3913 
3914    Note:
3915    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3916    call `MatSolveAdd`(A,x,y,x).
3917 
3918 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3919 @*/
3920 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3921 {
3922   PetscScalar one = 1.0;
3923   Vec         tmp;
3924 
3925   PetscFunctionBegin;
3926   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3927   PetscValidType(mat, 1);
3928   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3929   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3930   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3931   PetscCheckSameComm(mat, 1, b, 2);
3932   PetscCheckSameComm(mat, 1, y, 3);
3933   PetscCheckSameComm(mat, 1, x, 4);
3934   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3935   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);
3936   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);
3937   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);
3938   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);
3939   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);
3940   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3941   MatCheckPreallocated(mat, 1);
3942 
3943   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3944   if (mat->factorerrortype) {
3945     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3946     PetscCall(VecSetInf(x));
3947   } else if (mat->ops->solveadd) {
3948     PetscUseTypeMethod(mat, solveadd, b, y, x);
3949   } else {
3950     /* do the solve then the add manually */
3951     if (x != y) {
3952       PetscCall(MatSolve(mat, b, x));
3953       PetscCall(VecAXPY(x, one, y));
3954     } else {
3955       PetscCall(VecDuplicate(x, &tmp));
3956       PetscCall(VecCopy(x, tmp));
3957       PetscCall(MatSolve(mat, b, x));
3958       PetscCall(VecAXPY(x, one, tmp));
3959       PetscCall(VecDestroy(&tmp));
3960     }
3961   }
3962   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3963   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3964   PetscFunctionReturn(PETSC_SUCCESS);
3965 }
3966 
3967 /*@
3968    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3969 
3970    Neighbor-wise Collective
3971 
3972    Input Parameters:
3973 +  mat - the factored matrix
3974 -  b - the right-hand-side vector
3975 
3976    Output Parameter:
3977 .  x - the result vector
3978 
3979    Level: developer
3980 
3981    Notes:
3982    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3983    call `MatSolveTranspose`(A,x,x).
3984 
3985    Most users should employ the `KSP` interface for linear solvers
3986    instead of working directly with matrix algebra routines such as this.
3987    See, e.g., `KSPCreate()`.
3988 
3989 .seealso: `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3990 @*/
3991 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3992 {
3993   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3994 
3995   PetscFunctionBegin;
3996   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3997   PetscValidType(mat, 1);
3998   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3999   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
4000   PetscCheckSameComm(mat, 1, b, 2);
4001   PetscCheckSameComm(mat, 1, x, 3);
4002   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4003   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);
4004   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);
4005   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4006   MatCheckPreallocated(mat, 1);
4007   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
4008   if (mat->factorerrortype) {
4009     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4010     PetscCall(VecSetInf(x));
4011   } else {
4012     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4013     PetscCall((*f)(mat, b, x));
4014   }
4015   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4016   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4017   PetscFunctionReturn(PETSC_SUCCESS);
4018 }
4019 
4020 /*@
4021    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4022                       factored matrix.
4023 
4024    Neighbor-wise Collective
4025 
4026    Input Parameters:
4027 +  mat - the factored matrix
4028 .  b - the right-hand-side vector
4029 -  y - the vector to be added to
4030 
4031    Output Parameter:
4032 .  x - the result vector
4033 
4034    Level: developer
4035 
4036    Note:
4037    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4038    call `MatSolveTransposeAdd`(A,x,y,x).
4039 
4040 .seealso: `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4041 @*/
4042 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4043 {
4044   PetscScalar one = 1.0;
4045   Vec         tmp;
4046   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4047 
4048   PetscFunctionBegin;
4049   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4050   PetscValidType(mat, 1);
4051   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4052   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4053   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4054   PetscCheckSameComm(mat, 1, b, 2);
4055   PetscCheckSameComm(mat, 1, y, 3);
4056   PetscCheckSameComm(mat, 1, x, 4);
4057   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4058   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);
4059   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);
4060   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);
4061   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);
4062   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4063   MatCheckPreallocated(mat, 1);
4064 
4065   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4066   if (mat->factorerrortype) {
4067     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4068     PetscCall(VecSetInf(x));
4069   } else if (f) {
4070     PetscCall((*f)(mat, b, y, x));
4071   } else {
4072     /* do the solve then the add manually */
4073     if (x != y) {
4074       PetscCall(MatSolveTranspose(mat, b, x));
4075       PetscCall(VecAXPY(x, one, y));
4076     } else {
4077       PetscCall(VecDuplicate(x, &tmp));
4078       PetscCall(VecCopy(x, tmp));
4079       PetscCall(MatSolveTranspose(mat, b, x));
4080       PetscCall(VecAXPY(x, one, tmp));
4081       PetscCall(VecDestroy(&tmp));
4082     }
4083   }
4084   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4085   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4086   PetscFunctionReturn(PETSC_SUCCESS);
4087 }
4088 
4089 /*@
4090    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4091 
4092    Neighbor-wise Collective
4093 
4094    Input Parameters:
4095 +  mat - the matrix
4096 .  b - the right hand side
4097 .  omega - the relaxation factor
4098 .  flag - flag indicating the type of SOR (see below)
4099 .  shift -  diagonal shift
4100 .  its - the number of iterations
4101 -  lits - the number of local iterations
4102 
4103    Output Parameter:
4104 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4105 
4106    SOR Flags:
4107 +     `SOR_FORWARD_SWEEP` - forward SOR
4108 .     `SOR_BACKWARD_SWEEP` - backward SOR
4109 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4110 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4111 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4112 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4113 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4114 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4115          upper/lower triangular part of matrix to
4116          vector (with omega)
4117 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4118 
4119    Level: developer
4120 
4121    Notes:
4122    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4123    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4124    on each processor.
4125 
4126    Application programmers will not generally use `MatSOR()` directly,
4127    but instead will employ the `KSP`/`PC` interface.
4128 
4129    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4130 
4131    Most users should employ the `KSP` interface for linear solvers
4132    instead of working directly with matrix algebra routines such as this.
4133    See, e.g., `KSPCreate()`.
4134 
4135    Vectors `x` and `b` CANNOT be the same
4136 
4137    The flags are implemented as bitwise inclusive or operations.
4138    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4139    to specify a zero initial guess for SSOR.
4140 
4141    Developer Note:
4142    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4143 
4144 .seealso: `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4145 @*/
4146 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4147 {
4148   PetscFunctionBegin;
4149   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4150   PetscValidType(mat, 1);
4151   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4152   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4153   PetscCheckSameComm(mat, 1, b, 2);
4154   PetscCheckSameComm(mat, 1, x, 8);
4155   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4156   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4157   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);
4158   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);
4159   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);
4160   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4161   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4162   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4163 
4164   MatCheckPreallocated(mat, 1);
4165   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4166   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4167   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4168   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4169   PetscFunctionReturn(PETSC_SUCCESS);
4170 }
4171 
4172 /*
4173       Default matrix copy routine.
4174 */
4175 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4176 {
4177   PetscInt           i, rstart = 0, rend = 0, nz;
4178   const PetscInt    *cwork;
4179   const PetscScalar *vwork;
4180 
4181   PetscFunctionBegin;
4182   if (B->assembled) PetscCall(MatZeroEntries(B));
4183   if (str == SAME_NONZERO_PATTERN) {
4184     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4185     for (i = rstart; i < rend; i++) {
4186       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4187       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4188       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4189     }
4190   } else {
4191     PetscCall(MatAYPX(B, 0.0, A, str));
4192   }
4193   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4194   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4195   PetscFunctionReturn(PETSC_SUCCESS);
4196 }
4197 
4198 /*@
4199    MatCopy - Copies a matrix to another matrix.
4200 
4201    Collective
4202 
4203    Input Parameters:
4204 +  A - the matrix
4205 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4206 
4207    Output Parameter:
4208 .  B - where the copy is put
4209 
4210    Level: intermediate
4211 
4212    Notes:
4213    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4214 
4215    `MatCopy()` copies the matrix entries of a matrix to another existing
4216    matrix (after first zeroing the second matrix).  A related routine is
4217    `MatConvert()`, which first creates a new matrix and then copies the data.
4218 
4219 .seealso: `Mat`, `MatConvert()`, `MatDuplicate()`
4220 @*/
4221 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4222 {
4223   PetscInt i;
4224 
4225   PetscFunctionBegin;
4226   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4227   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4228   PetscValidType(A, 1);
4229   PetscValidType(B, 2);
4230   PetscCheckSameComm(A, 1, B, 2);
4231   MatCheckPreallocated(B, 2);
4232   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4233   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4234   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,
4235              A->cmap->N, B->cmap->N);
4236   MatCheckPreallocated(A, 1);
4237   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4238 
4239   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4240   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4241   else PetscCall(MatCopy_Basic(A, B, str));
4242 
4243   B->stencil.dim = A->stencil.dim;
4244   B->stencil.noc = A->stencil.noc;
4245   for (i = 0; i <= A->stencil.dim; i++) {
4246     B->stencil.dims[i]   = A->stencil.dims[i];
4247     B->stencil.starts[i] = A->stencil.starts[i];
4248   }
4249 
4250   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4251   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4252   PetscFunctionReturn(PETSC_SUCCESS);
4253 }
4254 
4255 /*@C
4256    MatConvert - Converts a matrix to another matrix, either of the same
4257    or different type.
4258 
4259    Collective
4260 
4261    Input Parameters:
4262 +  mat - the matrix
4263 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4264    same type as the original matrix.
4265 -  reuse - denotes if the destination matrix is to be created or reused.
4266    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
4267    `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).
4268 
4269    Output Parameter:
4270 .  M - pointer to place new matrix
4271 
4272    Level: intermediate
4273 
4274    Notes:
4275    `MatConvert()` first creates a new matrix and then copies the data from
4276    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4277    entries of one matrix to another already existing matrix context.
4278 
4279    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4280    the MPI communicator of the generated matrix is always the same as the communicator
4281    of the input matrix.
4282 
4283 .seealso: `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4284 @*/
4285 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4286 {
4287   PetscBool  sametype, issame, flg;
4288   PetscBool3 issymmetric, ishermitian;
4289   char       convname[256], mtype[256];
4290   Mat        B;
4291 
4292   PetscFunctionBegin;
4293   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4294   PetscValidType(mat, 1);
4295   PetscValidPointer(M, 4);
4296   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4297   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4298   MatCheckPreallocated(mat, 1);
4299 
4300   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4301   if (flg) newtype = mtype;
4302 
4303   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4304   PetscCall(PetscStrcmp(newtype, "same", &issame));
4305   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4306   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");
4307 
4308   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4309     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4310     PetscFunctionReturn(PETSC_SUCCESS);
4311   }
4312 
4313   /* Cache Mat options because some converters use MatHeaderReplace  */
4314   issymmetric = mat->symmetric;
4315   ishermitian = mat->hermitian;
4316 
4317   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4318     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4319     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4320   } else {
4321     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4322     const char *prefix[3]                                 = {"seq", "mpi", ""};
4323     PetscInt    i;
4324     /*
4325        Order of precedence:
4326        0) See if newtype is a superclass of the current matrix.
4327        1) See if a specialized converter is known to the current matrix.
4328        2) See if a specialized converter is known to the desired matrix class.
4329        3) See if a good general converter is registered for the desired class
4330           (as of 6/27/03 only MATMPIADJ falls into this category).
4331        4) See if a good general converter is known for the current matrix.
4332        5) Use a really basic converter.
4333     */
4334 
4335     /* 0) See if newtype is a superclass of the current matrix.
4336           i.e mat is mpiaij and newtype is aij */
4337     for (i = 0; i < 2; i++) {
4338       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4339       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4340       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4341       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4342       if (flg) {
4343         if (reuse == MAT_INPLACE_MATRIX) {
4344           PetscCall(PetscInfo(mat, "Early return\n"));
4345           PetscFunctionReturn(PETSC_SUCCESS);
4346         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4347           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4348           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4349           PetscFunctionReturn(PETSC_SUCCESS);
4350         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4351           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4352           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4353           PetscFunctionReturn(PETSC_SUCCESS);
4354         }
4355       }
4356     }
4357     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4358     for (i = 0; i < 3; i++) {
4359       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4360       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4361       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4362       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4363       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4365       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4366       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4367       if (conv) goto foundconv;
4368     }
4369 
4370     /* 2)  See if a specialized converter is known to the desired matrix class. */
4371     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4372     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4373     PetscCall(MatSetType(B, newtype));
4374     for (i = 0; i < 3; i++) {
4375       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4376       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4377       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4378       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4379       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4380       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4381       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4382       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4383       if (conv) {
4384         PetscCall(MatDestroy(&B));
4385         goto foundconv;
4386       }
4387     }
4388 
4389     /* 3) See if a good general converter is registered for the desired class */
4390     conv = B->ops->convertfrom;
4391     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4392     PetscCall(MatDestroy(&B));
4393     if (conv) goto foundconv;
4394 
4395     /* 4) See if a good general converter is known for the current matrix */
4396     if (mat->ops->convert) conv = mat->ops->convert;
4397     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4398     if (conv) goto foundconv;
4399 
4400     /* 5) Use a really basic converter. */
4401     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4402     conv = MatConvert_Basic;
4403 
4404   foundconv:
4405     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4406     PetscCall((*conv)(mat, newtype, reuse, M));
4407     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4408       /* the block sizes must be same if the mappings are copied over */
4409       (*M)->rmap->bs = mat->rmap->bs;
4410       (*M)->cmap->bs = mat->cmap->bs;
4411       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4412       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4413       (*M)->rmap->mapping = mat->rmap->mapping;
4414       (*M)->cmap->mapping = mat->cmap->mapping;
4415     }
4416     (*M)->stencil.dim = mat->stencil.dim;
4417     (*M)->stencil.noc = mat->stencil.noc;
4418     for (i = 0; i <= mat->stencil.dim; i++) {
4419       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4420       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4421     }
4422     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4423   }
4424   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4425 
4426   /* Copy Mat options */
4427   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4428   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4429   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4430   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4431   PetscFunctionReturn(PETSC_SUCCESS);
4432 }
4433 
4434 /*@C
4435    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4436 
4437    Not Collective
4438 
4439    Input Parameter:
4440 .  mat - the matrix, must be a factored matrix
4441 
4442    Output Parameter:
4443 .   type - the string name of the package (do not free this string)
4444 
4445    Level: intermediate
4446 
4447    Fortran Note:
4448    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4449 
4450 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4451 @*/
4452 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4453 {
4454   PetscErrorCode (*conv)(Mat, MatSolverType *);
4455 
4456   PetscFunctionBegin;
4457   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4458   PetscValidType(mat, 1);
4459   PetscValidPointer(type, 2);
4460   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4461   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4462   if (conv) PetscCall((*conv)(mat, type));
4463   else *type = MATSOLVERPETSC;
4464   PetscFunctionReturn(PETSC_SUCCESS);
4465 }
4466 
4467 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4468 struct _MatSolverTypeForSpecifcType {
4469   MatType mtype;
4470   /* no entry for MAT_FACTOR_NONE */
4471   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4472   MatSolverTypeForSpecifcType next;
4473 };
4474 
4475 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4476 struct _MatSolverTypeHolder {
4477   char                       *name;
4478   MatSolverTypeForSpecifcType handlers;
4479   MatSolverTypeHolder         next;
4480 };
4481 
4482 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4483 
4484 /*@C
4485    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4486 
4487    Input Parameters:
4488 +    package - name of the package, for example petsc or superlu
4489 .    mtype - the matrix type that works with this package
4490 .    ftype - the type of factorization supported by the package
4491 -    createfactor - routine that will create the factored matrix ready to be used
4492 
4493     Level: developer
4494 
4495 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4496 @*/
4497 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4498 {
4499   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4500   PetscBool                   flg;
4501   MatSolverTypeForSpecifcType inext, iprev = NULL;
4502 
4503   PetscFunctionBegin;
4504   PetscCall(MatInitializePackage());
4505   if (!next) {
4506     PetscCall(PetscNew(&MatSolverTypeHolders));
4507     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4508     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4509     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4510     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4511     PetscFunctionReturn(PETSC_SUCCESS);
4512   }
4513   while (next) {
4514     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4515     if (flg) {
4516       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4517       inext = next->handlers;
4518       while (inext) {
4519         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4520         if (flg) {
4521           inext->createfactor[(int)ftype - 1] = createfactor;
4522           PetscFunctionReturn(PETSC_SUCCESS);
4523         }
4524         iprev = inext;
4525         inext = inext->next;
4526       }
4527       PetscCall(PetscNew(&iprev->next));
4528       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4529       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4530       PetscFunctionReturn(PETSC_SUCCESS);
4531     }
4532     prev = next;
4533     next = next->next;
4534   }
4535   PetscCall(PetscNew(&prev->next));
4536   PetscCall(PetscStrallocpy(package, &prev->next->name));
4537   PetscCall(PetscNew(&prev->next->handlers));
4538   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4539   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4540   PetscFunctionReturn(PETSC_SUCCESS);
4541 }
4542 
4543 /*@C
4544    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4545 
4546    Input Parameters:
4547 +    type - name of the package, for example petsc or superlu
4548 .    ftype - the type of factorization supported by the type
4549 -    mtype - the matrix type that works with this type
4550 
4551    Output Parameters:
4552 +   foundtype - `PETSC_TRUE` if the type was registered
4553 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4554 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4555 
4556     Level: developer
4557 
4558 .seealso: `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4559 @*/
4560 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4561 {
4562   MatSolverTypeHolder         next = MatSolverTypeHolders;
4563   PetscBool                   flg;
4564   MatSolverTypeForSpecifcType inext;
4565 
4566   PetscFunctionBegin;
4567   if (foundtype) *foundtype = PETSC_FALSE;
4568   if (foundmtype) *foundmtype = PETSC_FALSE;
4569   if (createfactor) *createfactor = NULL;
4570 
4571   if (type) {
4572     while (next) {
4573       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4574       if (flg) {
4575         if (foundtype) *foundtype = PETSC_TRUE;
4576         inext = next->handlers;
4577         while (inext) {
4578           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4579           if (flg) {
4580             if (foundmtype) *foundmtype = PETSC_TRUE;
4581             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4582             PetscFunctionReturn(PETSC_SUCCESS);
4583           }
4584           inext = inext->next;
4585         }
4586       }
4587       next = next->next;
4588     }
4589   } else {
4590     while (next) {
4591       inext = next->handlers;
4592       while (inext) {
4593         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4594         if (flg && inext->createfactor[(int)ftype - 1]) {
4595           if (foundtype) *foundtype = PETSC_TRUE;
4596           if (foundmtype) *foundmtype = PETSC_TRUE;
4597           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4598           PetscFunctionReturn(PETSC_SUCCESS);
4599         }
4600         inext = inext->next;
4601       }
4602       next = next->next;
4603     }
4604     /* try with base classes inext->mtype */
4605     next = MatSolverTypeHolders;
4606     while (next) {
4607       inext = next->handlers;
4608       while (inext) {
4609         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4610         if (flg && inext->createfactor[(int)ftype - 1]) {
4611           if (foundtype) *foundtype = PETSC_TRUE;
4612           if (foundmtype) *foundmtype = PETSC_TRUE;
4613           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4614           PetscFunctionReturn(PETSC_SUCCESS);
4615         }
4616         inext = inext->next;
4617       }
4618       next = next->next;
4619     }
4620   }
4621   PetscFunctionReturn(PETSC_SUCCESS);
4622 }
4623 
4624 PetscErrorCode MatSolverTypeDestroy(void)
4625 {
4626   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4627   MatSolverTypeForSpecifcType inext, iprev;
4628 
4629   PetscFunctionBegin;
4630   while (next) {
4631     PetscCall(PetscFree(next->name));
4632     inext = next->handlers;
4633     while (inext) {
4634       PetscCall(PetscFree(inext->mtype));
4635       iprev = inext;
4636       inext = inext->next;
4637       PetscCall(PetscFree(iprev));
4638     }
4639     prev = next;
4640     next = next->next;
4641     PetscCall(PetscFree(prev));
4642   }
4643   MatSolverTypeHolders = NULL;
4644   PetscFunctionReturn(PETSC_SUCCESS);
4645 }
4646 
4647 /*@C
4648    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4649 
4650    Logically Collective
4651 
4652    Input Parameters:
4653 .  mat - the matrix
4654 
4655    Output Parameters:
4656 .  flg - `PETSC_TRUE` if uses the ordering
4657 
4658    Level: developer
4659 
4660    Note:
4661    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4662    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4663 
4664 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4665 @*/
4666 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4667 {
4668   PetscFunctionBegin;
4669   *flg = mat->canuseordering;
4670   PetscFunctionReturn(PETSC_SUCCESS);
4671 }
4672 
4673 /*@C
4674    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4675 
4676    Logically Collective
4677 
4678    Input Parameters:
4679 .  mat - the matrix obtained with `MatGetFactor()`
4680 
4681    Output Parameters:
4682 .  otype - the preferred type
4683 
4684    Level: developer
4685 
4686 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4687 @*/
4688 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4689 {
4690   PetscFunctionBegin;
4691   *otype = mat->preferredordering[ftype];
4692   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4693   PetscFunctionReturn(PETSC_SUCCESS);
4694 }
4695 
4696 /*@C
4697    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4698 
4699    Collective
4700 
4701    Input Parameters:
4702 +  mat - the matrix
4703 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4704 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4705 
4706    Output Parameters:
4707 .  f - the factor matrix used with MatXXFactorSymbolic() calls
4708 
4709    Options Database Key:
4710 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4711                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4712 
4713    Level: intermediate
4714 
4715    Notes:
4716      Users usually access the factorization solvers via `KSP`
4717 
4718       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4719      such as pastix, superlu, mumps etc.
4720 
4721       PETSc must have been ./configure to use the external solver, using the option --download-package
4722 
4723       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4724       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4725       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4726 
4727    Developer Note:
4728       This should actually be called `MatCreateFactor()` since it creates a new factor object
4729 
4730 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4731           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4732 @*/
4733 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4734 {
4735   PetscBool foundtype, foundmtype;
4736   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4737 
4738   PetscFunctionBegin;
4739   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4740   PetscValidType(mat, 1);
4741 
4742   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4743   MatCheckPreallocated(mat, 1);
4744 
4745   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4746   if (!foundtype) {
4747     if (type) {
4748       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],
4749               ((PetscObject)mat)->type_name, type);
4750     } else {
4751       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);
4752     }
4753   }
4754   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4755   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);
4756 
4757   PetscCall((*conv)(mat, ftype, f));
4758   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4759   PetscFunctionReturn(PETSC_SUCCESS);
4760 }
4761 
4762 /*@C
4763    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4764 
4765    Not Collective
4766 
4767    Input Parameters:
4768 +  mat - the matrix
4769 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4770 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4771 
4772    Output Parameter:
4773 .    flg - PETSC_TRUE if the factorization is available
4774 
4775    Level: intermediate
4776 
4777    Notes:
4778       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4779      such as pastix, superlu, mumps etc.
4780 
4781       PETSc must have been ./configure to use the external solver, using the option --download-package
4782 
4783    Developer Note:
4784       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4785 
4786 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4787           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4788 @*/
4789 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4790 {
4791   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4792 
4793   PetscFunctionBegin;
4794   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4795   PetscValidType(mat, 1);
4796   PetscValidBoolPointer(flg, 4);
4797 
4798   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4799   MatCheckPreallocated(mat, 1);
4800 
4801   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4802   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4803   PetscFunctionReturn(PETSC_SUCCESS);
4804 }
4805 
4806 /*@
4807    MatDuplicate - Duplicates a matrix including the non-zero structure.
4808 
4809    Collective
4810 
4811    Input Parameters:
4812 +  mat - the matrix
4813 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4814         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4815 
4816    Output Parameter:
4817 .  M - pointer to place new matrix
4818 
4819    Level: intermediate
4820 
4821    Notes:
4822     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4823 
4824     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.
4825 
4826     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
4827     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4828     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4829 
4830 .seealso: `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4831 @*/
4832 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4833 {
4834   Mat         B;
4835   VecType     vtype;
4836   PetscInt    i;
4837   PetscObject dm;
4838   void (*viewf)(void);
4839 
4840   PetscFunctionBegin;
4841   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4842   PetscValidType(mat, 1);
4843   PetscValidPointer(M, 3);
4844   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4845   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4846   MatCheckPreallocated(mat, 1);
4847 
4848   *M = NULL;
4849   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4850   PetscUseTypeMethod(mat, duplicate, op, M);
4851   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4852   B = *M;
4853 
4854   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4855   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4856   PetscCall(MatGetVecType(mat, &vtype));
4857   PetscCall(MatSetVecType(B, vtype));
4858 
4859   B->stencil.dim = mat->stencil.dim;
4860   B->stencil.noc = mat->stencil.noc;
4861   for (i = 0; i <= mat->stencil.dim; i++) {
4862     B->stencil.dims[i]   = mat->stencil.dims[i];
4863     B->stencil.starts[i] = mat->stencil.starts[i];
4864   }
4865 
4866   B->nooffproczerorows = mat->nooffproczerorows;
4867   B->nooffprocentries  = mat->nooffprocentries;
4868 
4869   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4870   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4871   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4872   PetscFunctionReturn(PETSC_SUCCESS);
4873 }
4874 
4875 /*@
4876    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4877 
4878    Logically Collective
4879 
4880    Input Parameters:
4881 +  mat - the matrix
4882 -  v - the vector for storing the diagonal
4883 
4884    Output Parameter:
4885 .  v - the diagonal of the matrix
4886 
4887    Level: intermediate
4888 
4889    Note:
4890    Currently only correct in parallel for square matrices.
4891 
4892 .seealso: `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4893 @*/
4894 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4895 {
4896   PetscFunctionBegin;
4897   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4898   PetscValidType(mat, 1);
4899   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4900   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4901   MatCheckPreallocated(mat, 1);
4902 
4903   PetscUseTypeMethod(mat, getdiagonal, v);
4904   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4905   PetscFunctionReturn(PETSC_SUCCESS);
4906 }
4907 
4908 /*@C
4909    MatGetRowMin - Gets the minimum value (of the real part) of each
4910         row of the matrix
4911 
4912    Logically Collective
4913 
4914    Input Parameter:
4915 .  mat - the matrix
4916 
4917    Output Parameters:
4918 +  v - the vector for storing the maximums
4919 -  idx - the indices of the column found for each row (optional)
4920 
4921    Level: intermediate
4922 
4923    Note:
4924     The result of this call are the same as if one converted the matrix to dense format
4925       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4926 
4927     This code is only implemented for a couple of matrix formats.
4928 
4929 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4930           `MatGetRowMax()`
4931 @*/
4932 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4933 {
4934   PetscFunctionBegin;
4935   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4936   PetscValidType(mat, 1);
4937   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4938   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4939 
4940   if (!mat->cmap->N) {
4941     PetscCall(VecSet(v, PETSC_MAX_REAL));
4942     if (idx) {
4943       PetscInt i, m = mat->rmap->n;
4944       for (i = 0; i < m; i++) idx[i] = -1;
4945     }
4946   } else {
4947     MatCheckPreallocated(mat, 1);
4948   }
4949   PetscUseTypeMethod(mat, getrowmin, v, idx);
4950   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4951   PetscFunctionReturn(PETSC_SUCCESS);
4952 }
4953 
4954 /*@C
4955    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4956         row of the matrix
4957 
4958    Logically Collective
4959 
4960    Input Parameter:
4961 .  mat - the matrix
4962 
4963    Output Parameters:
4964 +  v - the vector for storing the minimums
4965 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4966 
4967    Level: intermediate
4968 
4969    Notes:
4970     if a row is completely empty or has only 0.0 values then the idx[] value for that
4971     row is 0 (the first column).
4972 
4973     This code is only implemented for a couple of matrix formats.
4974 
4975 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4976 @*/
4977 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4978 {
4979   PetscFunctionBegin;
4980   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4981   PetscValidType(mat, 1);
4982   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4983   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4984   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4985 
4986   if (!mat->cmap->N) {
4987     PetscCall(VecSet(v, 0.0));
4988     if (idx) {
4989       PetscInt i, m = mat->rmap->n;
4990       for (i = 0; i < m; i++) idx[i] = -1;
4991     }
4992   } else {
4993     MatCheckPreallocated(mat, 1);
4994     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4995     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4996   }
4997   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4998   PetscFunctionReturn(PETSC_SUCCESS);
4999 }
5000 
5001 /*@C
5002    MatGetRowMax - Gets the maximum value (of the real part) of each
5003         row of the matrix
5004 
5005    Logically Collective
5006 
5007    Input Parameter:
5008 .  mat - the matrix
5009 
5010    Output Parameters:
5011 +  v - the vector for storing the maximums
5012 -  idx - the indices of the column found for each row (optional)
5013 
5014    Level: intermediate
5015 
5016    Notes:
5017     The result of this call are the same as if one converted the matrix to dense format
5018       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5019 
5020     This code is only implemented for a couple of matrix formats.
5021 
5022 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5023 @*/
5024 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5025 {
5026   PetscFunctionBegin;
5027   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5028   PetscValidType(mat, 1);
5029   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5030   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5031 
5032   if (!mat->cmap->N) {
5033     PetscCall(VecSet(v, PETSC_MIN_REAL));
5034     if (idx) {
5035       PetscInt i, m = mat->rmap->n;
5036       for (i = 0; i < m; i++) idx[i] = -1;
5037     }
5038   } else {
5039     MatCheckPreallocated(mat, 1);
5040     PetscUseTypeMethod(mat, getrowmax, v, idx);
5041   }
5042   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5043   PetscFunctionReturn(PETSC_SUCCESS);
5044 }
5045 
5046 /*@C
5047    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5048         row of the matrix
5049 
5050    Logically Collective
5051 
5052    Input Parameter:
5053 .  mat - the matrix
5054 
5055    Output Parameters:
5056 +  v - the vector for storing the maximums
5057 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5058 
5059    Level: intermediate
5060 
5061    Notes:
5062     if a row is completely empty or has only 0.0 values then the idx[] value for that
5063     row is 0 (the first column).
5064 
5065     This code is only implemented for a couple of matrix formats.
5066 
5067 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5068 @*/
5069 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5070 {
5071   PetscFunctionBegin;
5072   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5073   PetscValidType(mat, 1);
5074   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5075   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5076 
5077   if (!mat->cmap->N) {
5078     PetscCall(VecSet(v, 0.0));
5079     if (idx) {
5080       PetscInt i, m = mat->rmap->n;
5081       for (i = 0; i < m; i++) idx[i] = -1;
5082     }
5083   } else {
5084     MatCheckPreallocated(mat, 1);
5085     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5086     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5087   }
5088   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5089   PetscFunctionReturn(PETSC_SUCCESS);
5090 }
5091 
5092 /*@
5093    MatGetRowSum - Gets the sum of each row of the matrix
5094 
5095    Logically or Neighborhood Collective
5096 
5097    Input Parameters:
5098 .  mat - the matrix
5099 
5100    Output Parameter:
5101 .  v - the vector for storing the sum of rows
5102 
5103    Level: intermediate
5104 
5105    Notes:
5106     This code is slow since it is not currently specialized for different formats
5107 
5108 .seealso: `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5109 @*/
5110 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5111 {
5112   Vec ones;
5113 
5114   PetscFunctionBegin;
5115   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5116   PetscValidType(mat, 1);
5117   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5118   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5119   MatCheckPreallocated(mat, 1);
5120   PetscCall(MatCreateVecs(mat, &ones, NULL));
5121   PetscCall(VecSet(ones, 1.));
5122   PetscCall(MatMult(mat, ones, v));
5123   PetscCall(VecDestroy(&ones));
5124   PetscFunctionReturn(PETSC_SUCCESS);
5125 }
5126 
5127 /*@
5128    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5129    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5130 
5131    Collective
5132 
5133    Input Parameter:
5134 .  mat - the matrix to provide the transpose
5135 
5136    Output Parameter:
5137 .  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
5138 
5139    Level: advanced
5140 
5141    Note:
5142    Normally the use of `MatTranspose`(A, `MAT_REUSE_MATRIX`, &B) requires that `B` was obtained with a call to `MatTranspose`(A, `MAT_INITIAL_MATRIX`, &B). This
5143    routine allows bypassing that call.
5144 
5145 .seealso: `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5146 @*/
5147 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5148 {
5149   PetscContainer  rB = NULL;
5150   MatParentState *rb = NULL;
5151 
5152   PetscFunctionBegin;
5153   PetscCall(PetscNew(&rb));
5154   rb->id    = ((PetscObject)mat)->id;
5155   rb->state = 0;
5156   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5157   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5158   PetscCall(PetscContainerSetPointer(rB, rb));
5159   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5160   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5161   PetscCall(PetscObjectDereference((PetscObject)rB));
5162   PetscFunctionReturn(PETSC_SUCCESS);
5163 }
5164 
5165 /*@
5166    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5167 
5168    Collective
5169 
5170    Input Parameters:
5171 +  mat - the matrix to transpose
5172 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5173 
5174    Output Parameter:
5175 .  B - the transpose
5176 
5177    Level: intermediate
5178 
5179    Notes:
5180      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5181 
5182      `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
5183      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5184 
5185      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.
5186 
5187      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5188 
5189      If mat is unchanged from the last call this function returns immediately without recomputing the result
5190 
5191      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5192 
5193 .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5194           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5195 @*/
5196 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5197 {
5198   PetscContainer  rB = NULL;
5199   MatParentState *rb = NULL;
5200 
5201   PetscFunctionBegin;
5202   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5203   PetscValidType(mat, 1);
5204   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5205   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5206   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5207   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5208   MatCheckPreallocated(mat, 1);
5209   if (reuse == MAT_REUSE_MATRIX) {
5210     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5211     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5212     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5213     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5214     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5215   }
5216 
5217   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5218   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5219     PetscUseTypeMethod(mat, transpose, reuse, B);
5220     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5221   }
5222   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5223 
5224   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5225   if (reuse != MAT_INPLACE_MATRIX) {
5226     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5227     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5228     rb->state        = ((PetscObject)mat)->state;
5229     rb->nonzerostate = mat->nonzerostate;
5230   }
5231   PetscFunctionReturn(PETSC_SUCCESS);
5232 }
5233 
5234 /*@
5235    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5236 
5237    Collective
5238 
5239    Input Parameters:
5240 .  A - the matrix to transpose
5241 
5242    Output Parameter:
5243 .  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
5244       numerical portion.
5245 
5246    Level: intermediate
5247 
5248    Note:
5249    This is not supported for many matrix types, use `MatTranspose()` in those cases
5250 
5251 .seealso: `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5252 @*/
5253 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5254 {
5255   PetscFunctionBegin;
5256   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5257   PetscValidType(A, 1);
5258   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5259   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5260   PetscCheck(A->ops->transposesymbolic, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
5261   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5262   PetscCall((*A->ops->transposesymbolic)(A, B));
5263   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5264 
5265   PetscCall(MatTransposeSetPrecursor(A, *B));
5266   PetscFunctionReturn(PETSC_SUCCESS);
5267 }
5268 
5269 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5270 {
5271   PetscContainer  rB;
5272   MatParentState *rb;
5273 
5274   PetscFunctionBegin;
5275   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5276   PetscValidType(A, 1);
5277   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5278   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5279   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5280   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5281   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5282   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5283   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5284   PetscFunctionReturn(PETSC_SUCCESS);
5285 }
5286 
5287 /*@
5288    MatIsTranspose - Test whether a matrix is another one's transpose,
5289         or its own, in which case it tests symmetry.
5290 
5291    Collective
5292 
5293    Input Parameters:
5294 +  A - the matrix to test
5295 -  B - the matrix to test against, this can equal the first parameter
5296 
5297    Output Parameters:
5298 .  flg - the result
5299 
5300    Level: intermediate
5301 
5302    Notes:
5303    Only available for `MATAIJ` matrices.
5304 
5305    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5306    test involves parallel copies of the block-offdiagonal parts of the matrix.
5307 
5308 .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5309 @*/
5310 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5311 {
5312   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5313 
5314   PetscFunctionBegin;
5315   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5316   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5317   PetscValidBoolPointer(flg, 4);
5318   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5319   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5320   *flg = PETSC_FALSE;
5321   if (f && g) {
5322     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5323     PetscCall((*f)(A, B, tol, flg));
5324   } else {
5325     MatType mattype;
5326 
5327     PetscCall(MatGetType(f ? B : A, &mattype));
5328     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5329   }
5330   PetscFunctionReturn(PETSC_SUCCESS);
5331 }
5332 
5333 /*@
5334    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5335 
5336    Collective
5337 
5338    Input Parameters:
5339 +  mat - the matrix to transpose and complex conjugate
5340 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5341 
5342    Output Parameter:
5343 .  B - the Hermitian transpose
5344 
5345    Level: intermediate
5346 
5347 .seealso: `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5348 @*/
5349 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5350 {
5351   PetscFunctionBegin;
5352   PetscCall(MatTranspose(mat, reuse, B));
5353 #if defined(PETSC_USE_COMPLEX)
5354   PetscCall(MatConjugate(*B));
5355 #endif
5356   PetscFunctionReturn(PETSC_SUCCESS);
5357 }
5358 
5359 /*@
5360    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5361 
5362    Collective
5363 
5364    Input Parameters:
5365 +  A - the matrix to test
5366 -  B - the matrix to test against, this can equal the first parameter
5367 
5368    Output Parameters:
5369 .  flg - the result
5370 
5371    Level: intermediate
5372 
5373    Notes:
5374    Only available for `MATAIJ` matrices.
5375 
5376    The sequential algorithm
5377    has a running time of the order of the number of nonzeros; the parallel
5378    test involves parallel copies of the block-offdiagonal parts of the matrix.
5379 
5380 .seealso: `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5381 @*/
5382 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5383 {
5384   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5385 
5386   PetscFunctionBegin;
5387   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5388   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5389   PetscValidBoolPointer(flg, 4);
5390   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5391   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5392   if (f && g) {
5393     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5394     PetscCall((*f)(A, B, tol, flg));
5395   }
5396   PetscFunctionReturn(PETSC_SUCCESS);
5397 }
5398 
5399 /*@
5400    MatPermute - Creates a new matrix with rows and columns permuted from the
5401    original.
5402 
5403    Collective
5404 
5405    Input Parameters:
5406 +  mat - the matrix to permute
5407 .  row - row permutation, each processor supplies only the permutation for its rows
5408 -  col - column permutation, each processor supplies only the permutation for its columns
5409 
5410    Output Parameters:
5411 .  B - the permuted matrix
5412 
5413    Level: advanced
5414 
5415    Note:
5416    The index sets map from row/col of permuted matrix to row/col of original matrix.
5417    The index sets should be on the same communicator as mat and have the same local sizes.
5418 
5419    Developer Note:
5420      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5421      exploit the fact that row and col are permutations, consider implementing the
5422      more general `MatCreateSubMatrix()` instead.
5423 
5424 .seealso: `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5425 @*/
5426 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5427 {
5428   PetscFunctionBegin;
5429   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5430   PetscValidType(mat, 1);
5431   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5432   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5433   PetscValidPointer(B, 4);
5434   PetscCheckSameComm(mat, 1, row, 2);
5435   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5436   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5437   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5438   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5439   MatCheckPreallocated(mat, 1);
5440 
5441   if (mat->ops->permute) {
5442     PetscUseTypeMethod(mat, permute, row, col, B);
5443     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5444   } else {
5445     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5446   }
5447   PetscFunctionReturn(PETSC_SUCCESS);
5448 }
5449 
5450 /*@
5451    MatEqual - Compares two matrices.
5452 
5453    Collective
5454 
5455    Input Parameters:
5456 +  A - the first matrix
5457 -  B - the second matrix
5458 
5459    Output Parameter:
5460 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5461 
5462    Level: intermediate
5463 
5464 .seealso: `Mat`
5465 @*/
5466 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5467 {
5468   PetscFunctionBegin;
5469   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5470   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5471   PetscValidType(A, 1);
5472   PetscValidType(B, 2);
5473   PetscValidBoolPointer(flg, 3);
5474   PetscCheckSameComm(A, 1, B, 2);
5475   MatCheckPreallocated(A, 1);
5476   MatCheckPreallocated(B, 2);
5477   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5478   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5479   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,
5480              B->cmap->N);
5481   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5482     PetscUseTypeMethod(A, equal, B, flg);
5483   } else {
5484     PetscCall(MatMultEqual(A, B, 10, flg));
5485   }
5486   PetscFunctionReturn(PETSC_SUCCESS);
5487 }
5488 
5489 /*@
5490    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5491    matrices that are stored as vectors.  Either of the two scaling
5492    matrices can be `NULL`.
5493 
5494    Collective
5495 
5496    Input Parameters:
5497 +  mat - the matrix to be scaled
5498 .  l - the left scaling vector (or `NULL`)
5499 -  r - the right scaling vector (or `NULL`)
5500 
5501    Level: intermediate
5502 
5503    Note:
5504    `MatDiagonalScale()` computes A = LAR, where
5505    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5506    The L scales the rows of the matrix, the R scales the columns of the matrix.
5507 
5508 .seealso: `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5509 @*/
5510 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5511 {
5512   PetscFunctionBegin;
5513   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5514   PetscValidType(mat, 1);
5515   if (l) {
5516     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5517     PetscCheckSameComm(mat, 1, l, 2);
5518   }
5519   if (r) {
5520     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5521     PetscCheckSameComm(mat, 1, r, 3);
5522   }
5523   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5524   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5525   MatCheckPreallocated(mat, 1);
5526   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5527 
5528   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5529   PetscUseTypeMethod(mat, diagonalscale, l, r);
5530   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5531   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5532   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5533   PetscFunctionReturn(PETSC_SUCCESS);
5534 }
5535 
5536 /*@
5537     MatScale - Scales all elements of a matrix by a given number.
5538 
5539     Logically Collective
5540 
5541     Input Parameters:
5542 +   mat - the matrix to be scaled
5543 -   a  - the scaling value
5544 
5545     Output Parameter:
5546 .   mat - the scaled matrix
5547 
5548     Level: intermediate
5549 
5550 .seealso: `Mat`, `MatDiagonalScale()`
5551 @*/
5552 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5553 {
5554   PetscFunctionBegin;
5555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5556   PetscValidType(mat, 1);
5557   PetscCheck(a == (PetscScalar)1.0 || mat->ops->scale, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
5558   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5559   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5560   PetscValidLogicalCollectiveScalar(mat, a, 2);
5561   MatCheckPreallocated(mat, 1);
5562 
5563   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5564   if (a != (PetscScalar)1.0) {
5565     PetscUseTypeMethod(mat, scale, a);
5566     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5567   }
5568   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5569   PetscFunctionReturn(PETSC_SUCCESS);
5570 }
5571 
5572 /*@
5573    MatNorm - Calculates various norms of a matrix.
5574 
5575    Collective
5576 
5577    Input Parameters:
5578 +  mat - the matrix
5579 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5580 
5581    Output Parameter:
5582 .  nrm - the resulting norm
5583 
5584    Level: intermediate
5585 
5586 .seealso: `Mat`
5587 @*/
5588 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5589 {
5590   PetscFunctionBegin;
5591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5592   PetscValidType(mat, 1);
5593   PetscValidRealPointer(nrm, 3);
5594 
5595   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5596   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5597   MatCheckPreallocated(mat, 1);
5598 
5599   PetscUseTypeMethod(mat, norm, type, nrm);
5600   PetscFunctionReturn(PETSC_SUCCESS);
5601 }
5602 
5603 /*
5604      This variable is used to prevent counting of MatAssemblyBegin() that
5605    are called from within a MatAssemblyEnd().
5606 */
5607 static PetscInt MatAssemblyEnd_InUse = 0;
5608 /*@
5609    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5610    be called after completing all calls to `MatSetValues()`.
5611 
5612    Collective
5613 
5614    Input Parameters:
5615 +  mat - the matrix
5616 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5617 
5618    Level: beginner
5619 
5620    Notes:
5621    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5622    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5623 
5624    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5625    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5626    using the matrix.
5627 
5628    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5629    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
5630    a global collective operation requiring all processes that share the matrix.
5631 
5632    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5633    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5634    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5635 
5636 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5637 @*/
5638 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5639 {
5640   PetscFunctionBegin;
5641   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5642   PetscValidType(mat, 1);
5643   MatCheckPreallocated(mat, 1);
5644   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5645   if (mat->assembled) {
5646     mat->was_assembled = PETSC_TRUE;
5647     mat->assembled     = PETSC_FALSE;
5648   }
5649 
5650   if (!MatAssemblyEnd_InUse) {
5651     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5652     PetscTryTypeMethod(mat, assemblybegin, type);
5653     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5654   } else PetscTryTypeMethod(mat, assemblybegin, type);
5655   PetscFunctionReturn(PETSC_SUCCESS);
5656 }
5657 
5658 /*@
5659    MatAssembled - Indicates if a matrix has been assembled and is ready for
5660      use; for example, in matrix-vector product.
5661 
5662    Not Collective
5663 
5664    Input Parameter:
5665 .  mat - the matrix
5666 
5667    Output Parameter:
5668 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5669 
5670    Level: advanced
5671 
5672 .seealso: `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5673 @*/
5674 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5675 {
5676   PetscFunctionBegin;
5677   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5678   PetscValidBoolPointer(assembled, 2);
5679   *assembled = mat->assembled;
5680   PetscFunctionReturn(PETSC_SUCCESS);
5681 }
5682 
5683 /*@
5684    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5685    be called after `MatAssemblyBegin()`.
5686 
5687    Collective on Mat
5688 
5689    Input Parameters:
5690 +  mat - the matrix
5691 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5692 
5693    Options Database Keys:
5694 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5695 .  -mat_view ::ascii_info_detail - Prints more detailed info
5696 .  -mat_view - Prints matrix in ASCII format
5697 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5698 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5699 .  -display <name> - Sets display name (default is host)
5700 .  -draw_pause <sec> - Sets number of seconds to pause after display
5701 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5702 .  -viewer_socket_machine <machine> - Machine to use for socket
5703 .  -viewer_socket_port <port> - Port number to use for socket
5704 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5705 
5706    Level: beginner
5707 
5708 .seealso: `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5709 @*/
5710 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5711 {
5712   static PetscInt inassm = 0;
5713   PetscBool       flg    = PETSC_FALSE;
5714 
5715   PetscFunctionBegin;
5716   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5717   PetscValidType(mat, 1);
5718 
5719   inassm++;
5720   MatAssemblyEnd_InUse++;
5721   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5722     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5723     PetscTryTypeMethod(mat, assemblyend, type);
5724     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5725   } else PetscTryTypeMethod(mat, assemblyend, type);
5726 
5727   /* Flush assembly is not a true assembly */
5728   if (type != MAT_FLUSH_ASSEMBLY) {
5729     if (mat->num_ass) {
5730       if (!mat->symmetry_eternal) {
5731         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5732         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5733       }
5734       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5735       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5736     }
5737     mat->num_ass++;
5738     mat->assembled        = PETSC_TRUE;
5739     mat->ass_nonzerostate = mat->nonzerostate;
5740   }
5741 
5742   mat->insertmode = NOT_SET_VALUES;
5743   MatAssemblyEnd_InUse--;
5744   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5745   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5746     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5747 
5748     if (mat->checksymmetryonassembly) {
5749       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5750       if (flg) {
5751         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5752       } else {
5753         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5754       }
5755     }
5756     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5757   }
5758   inassm--;
5759   PetscFunctionReturn(PETSC_SUCCESS);
5760 }
5761 
5762 /*@
5763    MatSetOption - Sets a parameter option for a matrix. Some options
5764    may be specific to certain storage formats.  Some options
5765    determine how values will be inserted (or added). Sorted,
5766    row-oriented input will generally assemble the fastest. The default
5767    is row-oriented.
5768 
5769    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5770 
5771    Input Parameters:
5772 +  mat - the matrix
5773 .  option - the option, one of those listed below (and possibly others),
5774 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5775 
5776   Options Describing Matrix Structure:
5777 +    `MAT_SPD` - symmetric positive definite
5778 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5779 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5780 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5781 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5782 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5783 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5784 
5785    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5786    do not need to be computed (usually at a high cost)
5787 
5788    Options For Use with `MatSetValues()`:
5789    Insert a logically dense subblock, which can be
5790 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5791 
5792    These options reflect the data you pass in with `MatSetValues()`; it has
5793    nothing to do with how the data is stored internally in the matrix
5794    data structure.
5795 
5796    When (re)assembling a matrix, we can restrict the input for
5797    efficiency/debugging purposes.  These options include
5798 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5799 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5800 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5801 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5802 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5803 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5804         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5805         performance for very large process counts.
5806 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5807         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5808         functions, instead sending only neighbor messages.
5809 
5810    Level: intermediate
5811 
5812    Notes:
5813    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5814 
5815    Some options are relevant only for particular matrix types and
5816    are thus ignored by others.  Other options are not supported by
5817    certain matrix types and will generate an error message if set.
5818 
5819    If using Fortran to compute a matrix, one may need to
5820    use the column-oriented option (or convert to the row-oriented
5821    format).
5822 
5823    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5824    that would generate a new entry in the nonzero structure is instead
5825    ignored.  Thus, if memory has not already been allocated for this particular
5826    data, then the insertion is ignored. For dense matrices, in which
5827    the entire array is allocated, no entries are ever ignored.
5828    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5829 
5830    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5831    that would generate a new entry in the nonzero structure instead produces
5832    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
5833 
5834    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5835    that would generate a new entry that has not been preallocated will
5836    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5837    only.) This is a useful flag when debugging matrix memory preallocation.
5838    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5839 
5840    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5841    other processors should be dropped, rather than stashed.
5842    This is useful if you know that the "owning" processor is also
5843    always generating the correct matrix entries, so that PETSc need
5844    not transfer duplicate entries generated on another processor.
5845 
5846    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5847    searches during matrix assembly. When this flag is set, the hash table
5848    is created during the first matrix assembly. This hash table is
5849    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5850    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5851    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5852    supported by `MATMPIBAIJ` format only.
5853 
5854    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5855    are kept in the nonzero structure
5856 
5857    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5858    a zero location in the matrix
5859 
5860    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5861 
5862    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5863         zero row routines and thus improves performance for very large process counts.
5864 
5865    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5866         part of the matrix (since they should match the upper triangular part).
5867 
5868    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5869                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5870                      with finite difference schemes with non-periodic boundary conditions.
5871 
5872    Developer Note:
5873    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5874    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5875    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5876    not changed.
5877 
5878 .seealso: `MatOption`, `Mat`, `MatGetOption()`
5879 @*/
5880 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5881 {
5882   PetscFunctionBegin;
5883   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5884   if (op > 0) {
5885     PetscValidLogicalCollectiveEnum(mat, op, 2);
5886     PetscValidLogicalCollectiveBool(mat, flg, 3);
5887   }
5888 
5889   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);
5890 
5891   switch (op) {
5892   case MAT_FORCE_DIAGONAL_ENTRIES:
5893     mat->force_diagonals = flg;
5894     PetscFunctionReturn(PETSC_SUCCESS);
5895   case MAT_NO_OFF_PROC_ENTRIES:
5896     mat->nooffprocentries = flg;
5897     PetscFunctionReturn(PETSC_SUCCESS);
5898   case MAT_SUBSET_OFF_PROC_ENTRIES:
5899     mat->assembly_subset = flg;
5900     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5901 #if !defined(PETSC_HAVE_MPIUNI)
5902       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5903 #endif
5904       mat->stash.first_assembly_done = PETSC_FALSE;
5905     }
5906     PetscFunctionReturn(PETSC_SUCCESS);
5907   case MAT_NO_OFF_PROC_ZERO_ROWS:
5908     mat->nooffproczerorows = flg;
5909     PetscFunctionReturn(PETSC_SUCCESS);
5910   case MAT_SPD:
5911     if (flg) {
5912       mat->spd                    = PETSC_BOOL3_TRUE;
5913       mat->symmetric              = PETSC_BOOL3_TRUE;
5914       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5915     } else {
5916       mat->spd = PETSC_BOOL3_FALSE;
5917     }
5918     break;
5919   case MAT_SYMMETRIC:
5920     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5921     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5922 #if !defined(PETSC_USE_COMPLEX)
5923     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5924 #endif
5925     break;
5926   case MAT_HERMITIAN:
5927     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5928     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5929 #if !defined(PETSC_USE_COMPLEX)
5930     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5931 #endif
5932     break;
5933   case MAT_STRUCTURALLY_SYMMETRIC:
5934     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5935     break;
5936   case MAT_SYMMETRY_ETERNAL:
5937     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");
5938     mat->symmetry_eternal = flg;
5939     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5940     break;
5941   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5942     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");
5943     mat->structural_symmetry_eternal = flg;
5944     break;
5945   case MAT_SPD_ETERNAL:
5946     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");
5947     mat->spd_eternal = flg;
5948     if (flg) {
5949       mat->structural_symmetry_eternal = PETSC_TRUE;
5950       mat->symmetry_eternal            = PETSC_TRUE;
5951     }
5952     break;
5953   case MAT_STRUCTURE_ONLY:
5954     mat->structure_only = flg;
5955     break;
5956   case MAT_SORTED_FULL:
5957     mat->sortedfull = flg;
5958     break;
5959   default:
5960     break;
5961   }
5962   PetscTryTypeMethod(mat, setoption, op, flg);
5963   PetscFunctionReturn(PETSC_SUCCESS);
5964 }
5965 
5966 /*@
5967    MatGetOption - Gets a parameter option that has been set for a matrix.
5968 
5969    Logically Collective
5970 
5971    Input Parameters:
5972 +  mat - the matrix
5973 -  option - the option, this only responds to certain options, check the code for which ones
5974 
5975    Output Parameter:
5976 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5977 
5978    Level: intermediate
5979 
5980     Notes:
5981     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5982 
5983     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5984     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5985 
5986 .seealso: `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5987     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5988 @*/
5989 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5990 {
5991   PetscFunctionBegin;
5992   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5993   PetscValidType(mat, 1);
5994 
5995   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);
5996   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()");
5997 
5998   switch (op) {
5999   case MAT_NO_OFF_PROC_ENTRIES:
6000     *flg = mat->nooffprocentries;
6001     break;
6002   case MAT_NO_OFF_PROC_ZERO_ROWS:
6003     *flg = mat->nooffproczerorows;
6004     break;
6005   case MAT_SYMMETRIC:
6006     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
6007     break;
6008   case MAT_HERMITIAN:
6009     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6010     break;
6011   case MAT_STRUCTURALLY_SYMMETRIC:
6012     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6013     break;
6014   case MAT_SPD:
6015     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6016     break;
6017   case MAT_SYMMETRY_ETERNAL:
6018     *flg = mat->symmetry_eternal;
6019     break;
6020   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6021     *flg = mat->symmetry_eternal;
6022     break;
6023   default:
6024     break;
6025   }
6026   PetscFunctionReturn(PETSC_SUCCESS);
6027 }
6028 
6029 /*@
6030    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6031    this routine retains the old nonzero structure.
6032 
6033    Logically Collective
6034 
6035    Input Parameters:
6036 .  mat - the matrix
6037 
6038    Level: intermediate
6039 
6040    Note:
6041     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.
6042    See the Performance chapter of the users manual for information on preallocating matrices.
6043 
6044 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6045 @*/
6046 PetscErrorCode MatZeroEntries(Mat mat)
6047 {
6048   PetscFunctionBegin;
6049   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6050   PetscValidType(mat, 1);
6051   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6052   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");
6053   MatCheckPreallocated(mat, 1);
6054 
6055   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6056   PetscUseTypeMethod(mat, zeroentries);
6057   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6058   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6059   PetscFunctionReturn(PETSC_SUCCESS);
6060 }
6061 
6062 /*@
6063    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6064    of a set of rows and columns of a matrix.
6065 
6066    Collective
6067 
6068    Input Parameters:
6069 +  mat - the matrix
6070 .  numRows - the number of rows/columns to zero
6071 .  rows - the global row indices
6072 .  diag - value put in the diagonal of the eliminated rows
6073 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6074 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6075 
6076    Level: intermediate
6077 
6078    Notes:
6079    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6080 
6081    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6082    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
6083 
6084    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6085    Krylov method to take advantage of the known solution on the zeroed rows.
6086 
6087    For the parallel case, all processes that share the matrix (i.e.,
6088    those in the communicator used for matrix creation) MUST call this
6089    routine, regardless of whether any rows being zeroed are owned by
6090    them.
6091 
6092    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6093 
6094    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6095    list only rows local to itself).
6096 
6097    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6098 
6099 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6100           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6101 @*/
6102 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6103 {
6104   PetscFunctionBegin;
6105   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6106   PetscValidType(mat, 1);
6107   if (numRows) PetscValidIntPointer(rows, 3);
6108   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6109   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6110   MatCheckPreallocated(mat, 1);
6111 
6112   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6113   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6114   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6115   PetscFunctionReturn(PETSC_SUCCESS);
6116 }
6117 
6118 /*@
6119    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6120    of a set of rows and columns of a matrix.
6121 
6122    Collective
6123 
6124    Input Parameters:
6125 +  mat - the matrix
6126 .  is - the rows to zero
6127 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6128 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6129 -  b - optional vector of right hand side, that will be adjusted by provided solution
6130 
6131    Level: intermediate
6132 
6133    Note:
6134    See `MatZeroRowsColumns()` for details on how this routine operates.
6135 
6136 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6137           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6138 @*/
6139 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6140 {
6141   PetscInt        numRows;
6142   const PetscInt *rows;
6143 
6144   PetscFunctionBegin;
6145   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6146   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6147   PetscValidType(mat, 1);
6148   PetscValidType(is, 2);
6149   PetscCall(ISGetLocalSize(is, &numRows));
6150   PetscCall(ISGetIndices(is, &rows));
6151   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6152   PetscCall(ISRestoreIndices(is, &rows));
6153   PetscFunctionReturn(PETSC_SUCCESS);
6154 }
6155 
6156 /*@
6157    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6158    of a set of rows of a matrix.
6159 
6160    Collective
6161 
6162    Input Parameters:
6163 +  mat - the matrix
6164 .  numRows - the number of rows to zero
6165 .  rows - the global row indices
6166 .  diag - value put in the diagonal of the zeroed rows
6167 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6168 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6169 
6170    Level: intermediate
6171 
6172    Notes:
6173    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6174 
6175    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6176 
6177    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6178    Krylov method to take advantage of the known solution on the zeroed rows.
6179 
6180    May be followed by using a `PC` of type `PCREDISTRIBUTE` to solve the reduced problem (`PCDISTRIBUTE` completely eliminates the zeroed rows and their corresponding columns)
6181    from the matrix.
6182 
6183    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6184    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
6185    formats this does not alter the nonzero structure.
6186 
6187    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6188    of the matrix is not changed the values are
6189    merely zeroed.
6190 
6191    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6192    formats can optionally remove the main diagonal entry from the
6193    nonzero structure as well, by passing 0.0 as the final argument).
6194 
6195    For the parallel case, all processes that share the matrix (i.e.,
6196    those in the communicator used for matrix creation) MUST call this
6197    routine, regardless of whether any rows being zeroed are owned by
6198    them.
6199 
6200    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6201    list only rows local to itself).
6202 
6203    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6204    owns that are to be zeroed. This saves a global synchronization in the implementation.
6205 
6206 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6207           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6208 @*/
6209 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6210 {
6211   PetscFunctionBegin;
6212   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6213   PetscValidType(mat, 1);
6214   if (numRows) PetscValidIntPointer(rows, 3);
6215   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6216   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6217   MatCheckPreallocated(mat, 1);
6218 
6219   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6220   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6221   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6222   PetscFunctionReturn(PETSC_SUCCESS);
6223 }
6224 
6225 /*@
6226    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6227    of a set of rows of a matrix.
6228 
6229    Collective on Mat
6230 
6231    Input Parameters:
6232 +  mat - the matrix
6233 .  is - index set of rows to remove (if `NULL` then no row is removed)
6234 .  diag - value put in all diagonals of eliminated rows
6235 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6236 -  b - optional vector of right hand side, that will be adjusted by provided solution
6237 
6238    Level: intermediate
6239 
6240    Note:
6241    See `MatZeroRows()` for details on how this routine operates.
6242 
6243 .seealso: `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6244           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6245 @*/
6246 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6247 {
6248   PetscInt        numRows = 0;
6249   const PetscInt *rows    = NULL;
6250 
6251   PetscFunctionBegin;
6252   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6253   PetscValidType(mat, 1);
6254   if (is) {
6255     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6256     PetscCall(ISGetLocalSize(is, &numRows));
6257     PetscCall(ISGetIndices(is, &rows));
6258   }
6259   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6260   if (is) PetscCall(ISRestoreIndices(is, &rows));
6261   PetscFunctionReturn(PETSC_SUCCESS);
6262 }
6263 
6264 /*@
6265    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6266    of a set of rows of a matrix. These rows must be local to the process.
6267 
6268    Collective
6269 
6270    Input Parameters:
6271 +  mat - the matrix
6272 .  numRows - the number of rows to remove
6273 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6274 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6275 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6276 -  b - optional vector of right hand side, that will be adjusted by provided solution
6277 
6278    Level: intermediate
6279 
6280    Notes:
6281    See `MatZeroRows()` for details on how this routine operates.
6282 
6283    The grid coordinates are across the entire grid, not just the local portion
6284 
6285    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6286    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6287    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6288    `DM_BOUNDARY_PERIODIC` boundary type.
6289 
6290    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
6291    a single value per point) you can skip filling those indices.
6292 
6293    Fortran Note:
6294    `idxm` and `idxn` should be declared as
6295 $     MatStencil idxm(4,m)
6296    and the values inserted using
6297 .vb
6298     idxm(MatStencil_i,1) = i
6299     idxm(MatStencil_j,1) = j
6300     idxm(MatStencil_k,1) = k
6301     idxm(MatStencil_c,1) = c
6302    etc
6303 .ve
6304 
6305 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6306           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6307 @*/
6308 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6309 {
6310   PetscInt  dim    = mat->stencil.dim;
6311   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6312   PetscInt *dims   = mat->stencil.dims + 1;
6313   PetscInt *starts = mat->stencil.starts;
6314   PetscInt *dxm    = (PetscInt *)rows;
6315   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6316 
6317   PetscFunctionBegin;
6318   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6319   PetscValidType(mat, 1);
6320   if (numRows) PetscValidPointer(rows, 3);
6321 
6322   PetscCall(PetscMalloc1(numRows, &jdxm));
6323   for (i = 0; i < numRows; ++i) {
6324     /* Skip unused dimensions (they are ordered k, j, i, c) */
6325     for (j = 0; j < 3 - sdim; ++j) dxm++;
6326     /* Local index in X dir */
6327     tmp = *dxm++ - starts[0];
6328     /* Loop over remaining dimensions */
6329     for (j = 0; j < dim - 1; ++j) {
6330       /* If nonlocal, set index to be negative */
6331       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6332       /* Update local index */
6333       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6334     }
6335     /* Skip component slot if necessary */
6336     if (mat->stencil.noc) dxm++;
6337     /* Local row number */
6338     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6339   }
6340   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6341   PetscCall(PetscFree(jdxm));
6342   PetscFunctionReturn(PETSC_SUCCESS);
6343 }
6344 
6345 /*@
6346    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6347    of a set of rows and columns of a matrix.
6348 
6349    Collective
6350 
6351    Input Parameters:
6352 +  mat - the matrix
6353 .  numRows - the number of rows/columns to remove
6354 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6355 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6356 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6357 -  b - optional vector of right hand side, that will be adjusted by provided solution
6358 
6359    Level: intermediate
6360 
6361    Notes:
6362    See `MatZeroRowsColumns()` for details on how this routine operates.
6363 
6364    The grid coordinates are across the entire grid, not just the local portion
6365 
6366    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6367    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6368    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6369    `DM_BOUNDARY_PERIODIC` boundary type.
6370 
6371    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
6372    a single value per point) you can skip filling those indices.
6373 
6374    Fortran Note:
6375    `idxm` and `idxn` should be declared as
6376 $     MatStencil idxm(4,m)
6377    and the values inserted using
6378 .vb
6379     idxm(MatStencil_i,1) = i
6380     idxm(MatStencil_j,1) = j
6381     idxm(MatStencil_k,1) = k
6382     idxm(MatStencil_c,1) = c
6383     etc
6384 .ve
6385 
6386 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6387           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6388 @*/
6389 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6390 {
6391   PetscInt  dim    = mat->stencil.dim;
6392   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6393   PetscInt *dims   = mat->stencil.dims + 1;
6394   PetscInt *starts = mat->stencil.starts;
6395   PetscInt *dxm    = (PetscInt *)rows;
6396   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6397 
6398   PetscFunctionBegin;
6399   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6400   PetscValidType(mat, 1);
6401   if (numRows) PetscValidPointer(rows, 3);
6402 
6403   PetscCall(PetscMalloc1(numRows, &jdxm));
6404   for (i = 0; i < numRows; ++i) {
6405     /* Skip unused dimensions (they are ordered k, j, i, c) */
6406     for (j = 0; j < 3 - sdim; ++j) dxm++;
6407     /* Local index in X dir */
6408     tmp = *dxm++ - starts[0];
6409     /* Loop over remaining dimensions */
6410     for (j = 0; j < dim - 1; ++j) {
6411       /* If nonlocal, set index to be negative */
6412       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6413       /* Update local index */
6414       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6415     }
6416     /* Skip component slot if necessary */
6417     if (mat->stencil.noc) dxm++;
6418     /* Local row number */
6419     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6420   }
6421   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6422   PetscCall(PetscFree(jdxm));
6423   PetscFunctionReturn(PETSC_SUCCESS);
6424 }
6425 
6426 /*@C
6427    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6428    of a set of rows of a matrix; using local numbering of rows.
6429 
6430    Collective
6431 
6432    Input Parameters:
6433 +  mat - the matrix
6434 .  numRows - the number of rows to remove
6435 .  rows - the local row indices
6436 .  diag - value put in all diagonals of eliminated rows
6437 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6438 -  b - optional vector of right hand side, that will be adjusted by provided solution
6439 
6440    Level: intermediate
6441 
6442    Notes:
6443    Before calling `MatZeroRowsLocal()`, the user must first set the
6444    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6445 
6446    See `MatZeroRows()` for details on how this routine operates.
6447 
6448 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6449           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6450 @*/
6451 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6452 {
6453   PetscFunctionBegin;
6454   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6455   PetscValidType(mat, 1);
6456   if (numRows) PetscValidIntPointer(rows, 3);
6457   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6458   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6459   MatCheckPreallocated(mat, 1);
6460 
6461   if (mat->ops->zerorowslocal) {
6462     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6463   } else {
6464     IS              is, newis;
6465     const PetscInt *newRows;
6466 
6467     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6468     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6469     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6470     PetscCall(ISGetIndices(newis, &newRows));
6471     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6472     PetscCall(ISRestoreIndices(newis, &newRows));
6473     PetscCall(ISDestroy(&newis));
6474     PetscCall(ISDestroy(&is));
6475   }
6476   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6477   PetscFunctionReturn(PETSC_SUCCESS);
6478 }
6479 
6480 /*@
6481    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6482    of a set of rows of a matrix; using local numbering of rows.
6483 
6484    Collective
6485 
6486    Input Parameters:
6487 +  mat - the matrix
6488 .  is - index set of rows to remove
6489 .  diag - value put in all diagonals of eliminated rows
6490 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6491 -  b - optional vector of right hand side, that will be adjusted by provided solution
6492 
6493    Level: intermediate
6494 
6495    Notes:
6496    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6497    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6498 
6499    See `MatZeroRows()` for details on how this routine operates.
6500 
6501 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6502           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6503 @*/
6504 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6505 {
6506   PetscInt        numRows;
6507   const PetscInt *rows;
6508 
6509   PetscFunctionBegin;
6510   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6511   PetscValidType(mat, 1);
6512   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6513   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6514   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6515   MatCheckPreallocated(mat, 1);
6516 
6517   PetscCall(ISGetLocalSize(is, &numRows));
6518   PetscCall(ISGetIndices(is, &rows));
6519   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6520   PetscCall(ISRestoreIndices(is, &rows));
6521   PetscFunctionReturn(PETSC_SUCCESS);
6522 }
6523 
6524 /*@
6525    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6526    of a set of rows and columns of a matrix; using local numbering of rows.
6527 
6528    Collective
6529 
6530    Input Parameters:
6531 +  mat - the matrix
6532 .  numRows - the number of rows to remove
6533 .  rows - the global row indices
6534 .  diag - value put in all diagonals of eliminated rows
6535 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6536 -  b - optional vector of right hand side, that will be adjusted by provided solution
6537 
6538    Level: intermediate
6539 
6540    Notes:
6541    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6542    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6543 
6544    See `MatZeroRowsColumns()` for details on how this routine operates.
6545 
6546 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6547           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6548 @*/
6549 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6550 {
6551   IS              is, newis;
6552   const PetscInt *newRows;
6553 
6554   PetscFunctionBegin;
6555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6556   PetscValidType(mat, 1);
6557   if (numRows) PetscValidIntPointer(rows, 3);
6558   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6559   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6560   MatCheckPreallocated(mat, 1);
6561 
6562   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6563   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6564   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6565   PetscCall(ISGetIndices(newis, &newRows));
6566   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6567   PetscCall(ISRestoreIndices(newis, &newRows));
6568   PetscCall(ISDestroy(&newis));
6569   PetscCall(ISDestroy(&is));
6570   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6571   PetscFunctionReturn(PETSC_SUCCESS);
6572 }
6573 
6574 /*@
6575    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6576    of a set of rows and columns of a matrix; using local numbering of rows.
6577 
6578    Collective on Mat
6579 
6580    Input Parameters:
6581 +  mat - the matrix
6582 .  is - index set of rows to remove
6583 .  diag - value put in all diagonals of eliminated rows
6584 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6585 -  b - optional vector of right hand side, that will be adjusted by provided solution
6586 
6587    Level: intermediate
6588 
6589    Notes:
6590    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6591    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6592 
6593    See `MatZeroRowsColumns()` for details on how this routine operates.
6594 
6595 .seealso: `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6596           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6597 @*/
6598 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6599 {
6600   PetscInt        numRows;
6601   const PetscInt *rows;
6602 
6603   PetscFunctionBegin;
6604   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6605   PetscValidType(mat, 1);
6606   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6607   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6608   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6609   MatCheckPreallocated(mat, 1);
6610 
6611   PetscCall(ISGetLocalSize(is, &numRows));
6612   PetscCall(ISGetIndices(is, &rows));
6613   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6614   PetscCall(ISRestoreIndices(is, &rows));
6615   PetscFunctionReturn(PETSC_SUCCESS);
6616 }
6617 
6618 /*@C
6619    MatGetSize - Returns the numbers of rows and columns in a matrix.
6620 
6621    Not Collective
6622 
6623    Input Parameter:
6624 .  mat - the matrix
6625 
6626    Level: beginner
6627 
6628    Output Parameters:
6629 +  m - the number of global rows
6630 -  n - the number of global columns
6631 
6632    Note:
6633    Both output parameters can be `NULL` on input.
6634 
6635 .seealso: `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6636 @*/
6637 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6638 {
6639   PetscFunctionBegin;
6640   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6641   if (m) *m = mat->rmap->N;
6642   if (n) *n = mat->cmap->N;
6643   PetscFunctionReturn(PETSC_SUCCESS);
6644 }
6645 
6646 /*@C
6647    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6648    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6649 
6650    Not Collective
6651 
6652    Input Parameter:
6653 .  mat - the matrix
6654 
6655    Output Parameters:
6656 +  m - the number of local rows, use `NULL` to not obtain this value
6657 -  n - the number of local columns, use `NULL` to not obtain this value
6658 
6659    Level: beginner
6660 
6661 .seealso: `Mat`, `MatSetSizes()`, `MatGetSize()`
6662 @*/
6663 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6664 {
6665   PetscFunctionBegin;
6666   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6667   if (m) PetscValidIntPointer(m, 2);
6668   if (n) PetscValidIntPointer(n, 3);
6669   if (m) *m = mat->rmap->n;
6670   if (n) *n = mat->cmap->n;
6671   PetscFunctionReturn(PETSC_SUCCESS);
6672 }
6673 
6674 /*@C
6675    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6676    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6677 
6678    Not Collective, unless matrix has not been allocated, then collective
6679 
6680    Input Parameter:
6681 .  mat - the matrix
6682 
6683    Output Parameters:
6684 +  m - the global index of the first local column, use `NULL` to not obtain this value
6685 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6686 
6687    Level: developer
6688 
6689 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6690 @*/
6691 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6692 {
6693   PetscFunctionBegin;
6694   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6695   PetscValidType(mat, 1);
6696   if (m) PetscValidIntPointer(m, 2);
6697   if (n) PetscValidIntPointer(n, 3);
6698   MatCheckPreallocated(mat, 1);
6699   if (m) *m = mat->cmap->rstart;
6700   if (n) *n = mat->cmap->rend;
6701   PetscFunctionReturn(PETSC_SUCCESS);
6702 }
6703 
6704 /*@C
6705    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6706    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
6707    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6708 
6709    Not Collective
6710 
6711    Input Parameter:
6712 .  mat - the matrix
6713 
6714    Output Parameters:
6715 +  m - the global index of the first local row, use `NULL` to not obtain this value
6716 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6717 
6718    Level: beginner
6719 
6720    Note:
6721   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6722   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6723   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6724 
6725 .seealso: `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6726           `PetscLayout`
6727 @*/
6728 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6729 {
6730   PetscFunctionBegin;
6731   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6732   PetscValidType(mat, 1);
6733   if (m) PetscValidIntPointer(m, 2);
6734   if (n) PetscValidIntPointer(n, 3);
6735   MatCheckPreallocated(mat, 1);
6736   if (m) *m = mat->rmap->rstart;
6737   if (n) *n = mat->rmap->rend;
6738   PetscFunctionReturn(PETSC_SUCCESS);
6739 }
6740 
6741 /*@C
6742    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6743    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
6744    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6745 
6746    Not Collective, unless matrix has not been allocated, then collective
6747 
6748    Input Parameters:
6749 .  mat - the matrix
6750 
6751    Output Parameters:
6752 .  ranges - start of each processors portion plus one more than the total length at the end
6753 
6754    Level: beginner
6755 
6756 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6757 @*/
6758 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6759 {
6760   PetscFunctionBegin;
6761   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6762   PetscValidType(mat, 1);
6763   MatCheckPreallocated(mat, 1);
6764   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6765   PetscFunctionReturn(PETSC_SUCCESS);
6766 }
6767 
6768 /*@C
6769    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6770    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6771 
6772    Not Collective, unless matrix has not been allocated, then collective on Mat
6773 
6774    Input Parameters:
6775 .  mat - the matrix
6776 
6777    Output Parameters:
6778 .  ranges - start of each processors portion plus one more then the total length at the end
6779 
6780    Level: beginner
6781 
6782 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6783 @*/
6784 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6785 {
6786   PetscFunctionBegin;
6787   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6788   PetscValidType(mat, 1);
6789   MatCheckPreallocated(mat, 1);
6790   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6791   PetscFunctionReturn(PETSC_SUCCESS);
6792 }
6793 
6794 /*@C
6795    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6796    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6797    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6798 
6799    Not Collective
6800 
6801    Input Parameter:
6802 .  A - matrix
6803 
6804    Output Parameters:
6805 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6806 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6807 
6808    Level: intermediate
6809 
6810 .seealso: `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6811 @*/
6812 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6813 {
6814   PetscErrorCode (*f)(Mat, IS *, IS *);
6815 
6816   PetscFunctionBegin;
6817   MatCheckPreallocated(A, 1);
6818   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6819   if (f) {
6820     PetscCall((*f)(A, rows, cols));
6821   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6822     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6823     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6824   }
6825   PetscFunctionReturn(PETSC_SUCCESS);
6826 }
6827 
6828 /*@C
6829    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6830    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6831    to complete the factorization.
6832 
6833    Collective on fact
6834 
6835    Input Parameters:
6836 +  fact - the factorized matrix obtained with `MatGetFactor()`
6837 .  mat - the matrix
6838 .  row - row permutation
6839 .  column - column permutation
6840 -  info - structure containing
6841 .vb
6842       levels - number of levels of fill.
6843       expected fill - as ratio of original fill.
6844       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6845                 missing diagonal entries)
6846 .ve
6847 
6848    Output Parameters:
6849 .  fact - new matrix that has been symbolically factored
6850 
6851    Level: developer
6852 
6853    Notes:
6854    See [Matrix Factorization](sec_matfactor) for additional information.
6855 
6856    Most users should employ the `KSP` interface for linear solvers
6857    instead of working directly with matrix algebra routines such as this.
6858    See, e.g., `KSPCreate()`.
6859 
6860    Uses the definition of level of fill as in Y. Saad, 2003
6861 
6862    Developer Note:
6863    The Fortran interface is not autogenerated as the
6864    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6865 
6866    References:
6867 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6868 
6869 .seealso: `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6870           `MatGetOrdering()`, `MatFactorInfo`
6871 @*/
6872 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6873 {
6874   PetscFunctionBegin;
6875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6876   PetscValidType(mat, 2);
6877   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6878   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6879   PetscValidPointer(info, 5);
6880   PetscValidPointer(fact, 1);
6881   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6882   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6883   if (!fact->ops->ilufactorsymbolic) {
6884     MatSolverType stype;
6885     PetscCall(MatFactorGetSolverType(fact, &stype));
6886     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ILU using solver type %s", ((PetscObject)mat)->type_name, stype);
6887   }
6888   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6889   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6890   MatCheckPreallocated(mat, 2);
6891 
6892   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6893   PetscCall((fact->ops->ilufactorsymbolic)(fact, mat, row, col, info));
6894   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6895   PetscFunctionReturn(PETSC_SUCCESS);
6896 }
6897 
6898 /*@C
6899    MatICCFactorSymbolic - Performs symbolic incomplete
6900    Cholesky factorization for a symmetric matrix.  Use
6901    `MatCholeskyFactorNumeric()` to complete the factorization.
6902 
6903    Collective on fact
6904 
6905    Input Parameters:
6906 +  fact - the factorized matrix obtained with `MatGetFactor()`
6907 .  mat - the matrix to be factored
6908 .  perm - row and column permutation
6909 -  info - structure containing
6910 .vb
6911       levels - number of levels of fill.
6912       expected fill - as ratio of original fill.
6913 .ve
6914 
6915    Output Parameter:
6916 .  fact - the factored matrix
6917 
6918    Level: developer
6919 
6920    Notes:
6921    Most users should employ the `KSP` interface for linear solvers
6922    instead of working directly with matrix algebra routines such as this.
6923    See, e.g., `KSPCreate()`.
6924 
6925    This uses the definition of level of fill as in Y. Saad, 2003
6926 
6927    Developer Note:
6928    The Fortran interface is not autogenerated as the
6929    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6930 
6931    References:
6932 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6933 
6934 .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6935 @*/
6936 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6937 {
6938   PetscFunctionBegin;
6939   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6940   PetscValidType(mat, 2);
6941   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6942   PetscValidPointer(info, 4);
6943   PetscValidPointer(fact, 1);
6944   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6945   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6946   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6947   if (!(fact)->ops->iccfactorsymbolic) {
6948     MatSolverType stype;
6949     PetscCall(MatFactorGetSolverType(fact, &stype));
6950     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s symbolic ICC using solver type %s", ((PetscObject)mat)->type_name, stype);
6951   }
6952   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6953   MatCheckPreallocated(mat, 2);
6954 
6955   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6956   PetscCall((fact->ops->iccfactorsymbolic)(fact, mat, perm, info));
6957   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6958   PetscFunctionReturn(PETSC_SUCCESS);
6959 }
6960 
6961 /*@C
6962    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6963    points to an array of valid matrices, they may be reused to store the new
6964    submatrices.
6965 
6966    Collective
6967 
6968    Input Parameters:
6969 +  mat - the matrix
6970 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6971 .  irow, icol - index sets of rows and columns to extract
6972 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6973 
6974    Output Parameter:
6975 .  submat - the array of submatrices
6976 
6977    Level: advanced
6978 
6979    Notes:
6980    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6981    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6982    to extract a parallel submatrix.
6983 
6984    Some matrix types place restrictions on the row and column
6985    indices, such as that they be sorted or that they be equal to each other.
6986 
6987    The index sets may not have duplicate entries.
6988 
6989    When extracting submatrices from a parallel matrix, each processor can
6990    form a different submatrix by setting the rows and columns of its
6991    individual index sets according to the local submatrix desired.
6992 
6993    When finished using the submatrices, the user should destroy
6994    them with `MatDestroySubMatrices()`.
6995 
6996    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6997    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6998 
6999    This routine creates the matrices in submat; you should NOT create them before
7000    calling it. It also allocates the array of matrix pointers submat.
7001 
7002    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
7003    request one row/column in a block, they must request all rows/columns that are in
7004    that block. For example, if the block size is 2 you cannot request just row 0 and
7005    column 0.
7006 
7007    Fortran Note:
7008    The Fortran interface is slightly different from that given below; it
7009    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
7010 
7011 .seealso: `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7012 @*/
7013 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7014 {
7015   PetscInt  i;
7016   PetscBool eq;
7017 
7018   PetscFunctionBegin;
7019   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7020   PetscValidType(mat, 1);
7021   if (n) {
7022     PetscValidPointer(irow, 3);
7023     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7024     PetscValidPointer(icol, 4);
7025     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7026   }
7027   PetscValidPointer(submat, 6);
7028   if (n && scall == MAT_REUSE_MATRIX) {
7029     PetscValidPointer(*submat, 6);
7030     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7031   }
7032   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7033   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7034   MatCheckPreallocated(mat, 1);
7035   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7036   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7037   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7038   for (i = 0; i < n; i++) {
7039     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7040     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7041     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7042 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7043     if (mat->boundtocpu && mat->bindingpropagates) {
7044       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7045       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7046     }
7047 #endif
7048   }
7049   PetscFunctionReturn(PETSC_SUCCESS);
7050 }
7051 
7052 /*@C
7053    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7054 
7055    Collective
7056 
7057    Input Parameters:
7058 +  mat - the matrix
7059 .  n   - the number of submatrixes to be extracted
7060 .  irow, icol - index sets of rows and columns to extract
7061 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7062 
7063    Output Parameter:
7064 .  submat - the array of submatrices
7065 
7066    Level: advanced
7067 
7068    Note:
7069    This is used by `PCGASM`
7070 
7071 .seealso: `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7072 @*/
7073 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7074 {
7075   PetscInt  i;
7076   PetscBool eq;
7077 
7078   PetscFunctionBegin;
7079   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7080   PetscValidType(mat, 1);
7081   if (n) {
7082     PetscValidPointer(irow, 3);
7083     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7084     PetscValidPointer(icol, 4);
7085     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7086   }
7087   PetscValidPointer(submat, 6);
7088   if (n && scall == MAT_REUSE_MATRIX) {
7089     PetscValidPointer(*submat, 6);
7090     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7091   }
7092   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7093   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7094   MatCheckPreallocated(mat, 1);
7095 
7096   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7097   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7098   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7099   for (i = 0; i < n; i++) {
7100     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7101     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7102   }
7103   PetscFunctionReturn(PETSC_SUCCESS);
7104 }
7105 
7106 /*@C
7107    MatDestroyMatrices - Destroys an array of matrices.
7108 
7109    Collective
7110 
7111    Input Parameters:
7112 +  n - the number of local matrices
7113 -  mat - the matrices (this is a pointer to the array of matrices)
7114 
7115    Level: advanced
7116 
7117     Note:
7118     Frees not only the matrices, but also the array that contains the matrices
7119 
7120     Fortran Note:
7121     This does not free the array.
7122 
7123 .seealso: `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7124 @*/
7125 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7126 {
7127   PetscInt i;
7128 
7129   PetscFunctionBegin;
7130   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7131   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7132   PetscValidPointer(mat, 2);
7133 
7134   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7135 
7136   /* memory is allocated even if n = 0 */
7137   PetscCall(PetscFree(*mat));
7138   PetscFunctionReturn(PETSC_SUCCESS);
7139 }
7140 
7141 /*@C
7142    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7143 
7144    Collective
7145 
7146    Input Parameters:
7147 +  n - the number of local matrices
7148 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7149                        sequence of `MatCreateSubMatrices()`)
7150 
7151    Level: advanced
7152 
7153     Note:
7154     Frees not only the matrices, but also the array that contains the matrices
7155 
7156     Fortran Note:
7157     This does not free the array.
7158 
7159 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7160 @*/
7161 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7162 {
7163   Mat mat0;
7164 
7165   PetscFunctionBegin;
7166   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7167   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7168   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7169   PetscValidPointer(mat, 2);
7170 
7171   mat0 = (*mat)[0];
7172   if (mat0 && mat0->ops->destroysubmatrices) {
7173     PetscCall((mat0->ops->destroysubmatrices)(n, mat));
7174   } else {
7175     PetscCall(MatDestroyMatrices(n, mat));
7176   }
7177   PetscFunctionReturn(PETSC_SUCCESS);
7178 }
7179 
7180 /*@C
7181    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7182 
7183    Collective
7184 
7185    Input Parameters:
7186 .  mat - the matrix
7187 
7188    Output Parameter:
7189 .  matstruct - the sequential matrix with the nonzero structure of mat
7190 
7191   Level: developer
7192 
7193 .seealso: `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7194 @*/
7195 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7196 {
7197   PetscFunctionBegin;
7198   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7199   PetscValidPointer(matstruct, 2);
7200 
7201   PetscValidType(mat, 1);
7202   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7203   MatCheckPreallocated(mat, 1);
7204 
7205   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7206   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7207   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7208   PetscFunctionReturn(PETSC_SUCCESS);
7209 }
7210 
7211 /*@C
7212    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7213 
7214    Collective
7215 
7216    Input Parameters:
7217 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7218                        sequence of `MatGetSequentialNonzeroStructure()`)
7219 
7220    Level: advanced
7221 
7222     Note:
7223     Frees not only the matrices, but also the array that contains the matrices
7224 
7225 .seealso: `Mat`, `MatGetSeqNonzeroStructure()`
7226 @*/
7227 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7228 {
7229   PetscFunctionBegin;
7230   PetscValidPointer(mat, 1);
7231   PetscCall(MatDestroy(mat));
7232   PetscFunctionReturn(PETSC_SUCCESS);
7233 }
7234 
7235 /*@
7236    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7237    replaces the index sets by larger ones that represent submatrices with
7238    additional overlap.
7239 
7240    Collective
7241 
7242    Input Parameters:
7243 +  mat - the matrix
7244 .  n   - the number of index sets
7245 .  is  - the array of index sets (these index sets will changed during the call)
7246 -  ov  - the additional overlap requested
7247 
7248    Options Database Key:
7249 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7250 
7251    Level: developer
7252 
7253    Note:
7254    The computed overlap preserves the matrix block sizes when the blocks are square.
7255    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7256    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7257 
7258 .seealso: `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7259 @*/
7260 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7261 {
7262   PetscInt i, bs, cbs;
7263 
7264   PetscFunctionBegin;
7265   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7266   PetscValidType(mat, 1);
7267   PetscValidLogicalCollectiveInt(mat, n, 2);
7268   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7269   if (n) {
7270     PetscValidPointer(is, 3);
7271     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7272   }
7273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7275   MatCheckPreallocated(mat, 1);
7276 
7277   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7278   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7279   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7280   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7281   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7282   if (bs == cbs) {
7283     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7284   }
7285   PetscFunctionReturn(PETSC_SUCCESS);
7286 }
7287 
7288 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7289 
7290 /*@
7291    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7292    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7293    additional overlap.
7294 
7295    Collective
7296 
7297    Input Parameters:
7298 +  mat - the matrix
7299 .  n   - the number of index sets
7300 .  is  - the array of index sets (these index sets will changed during the call)
7301 -  ov  - the additional overlap requested
7302 
7303 `   Options Database Key:
7304 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7305 
7306    Level: developer
7307 
7308 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7309 @*/
7310 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7311 {
7312   PetscInt i;
7313 
7314   PetscFunctionBegin;
7315   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7316   PetscValidType(mat, 1);
7317   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7318   if (n) {
7319     PetscValidPointer(is, 3);
7320     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7321   }
7322   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7323   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7324   MatCheckPreallocated(mat, 1);
7325   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7326   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7327   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7328   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7329   PetscFunctionReturn(PETSC_SUCCESS);
7330 }
7331 
7332 /*@
7333    MatGetBlockSize - Returns the matrix block size.
7334 
7335    Not Collective
7336 
7337    Input Parameter:
7338 .  mat - the matrix
7339 
7340    Output Parameter:
7341 .  bs - block size
7342 
7343    Level: intermediate
7344 
7345    Notes:
7346     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7347 
7348    If the block size has not been set yet this routine returns 1.
7349 
7350 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7351 @*/
7352 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7353 {
7354   PetscFunctionBegin;
7355   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7356   PetscValidIntPointer(bs, 2);
7357   *bs = PetscAbs(mat->rmap->bs);
7358   PetscFunctionReturn(PETSC_SUCCESS);
7359 }
7360 
7361 /*@
7362    MatGetBlockSizes - Returns the matrix block row and column sizes.
7363 
7364    Not Collective
7365 
7366    Input Parameter:
7367 .  mat - the matrix
7368 
7369    Output Parameters:
7370 +  rbs - row block size
7371 -  cbs - column block size
7372 
7373    Level: intermediate
7374 
7375    Notes:
7376     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7377     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7378 
7379    If a block size has not been set yet this routine returns 1.
7380 
7381 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7382 @*/
7383 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7384 {
7385   PetscFunctionBegin;
7386   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7387   if (rbs) PetscValidIntPointer(rbs, 2);
7388   if (cbs) PetscValidIntPointer(cbs, 3);
7389   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7390   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7391   PetscFunctionReturn(PETSC_SUCCESS);
7392 }
7393 
7394 /*@
7395    MatSetBlockSize - Sets the matrix block size.
7396 
7397    Logically Collective
7398 
7399    Input Parameters:
7400 +  mat - the matrix
7401 -  bs - block size
7402 
7403    Level: intermediate
7404 
7405    Notes:
7406     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7407     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7408 
7409     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7410     is compatible with the matrix local sizes.
7411 
7412 .seealso: `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7413 @*/
7414 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7415 {
7416   PetscFunctionBegin;
7417   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7418   PetscValidLogicalCollectiveInt(mat, bs, 2);
7419   PetscCall(MatSetBlockSizes(mat, bs, bs));
7420   PetscFunctionReturn(PETSC_SUCCESS);
7421 }
7422 
7423 typedef struct {
7424   PetscInt         n;
7425   IS              *is;
7426   Mat             *mat;
7427   PetscObjectState nonzerostate;
7428   Mat              C;
7429 } EnvelopeData;
7430 
7431 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7432 {
7433   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7434   PetscCall(PetscFree(edata->is));
7435   PetscCall(PetscFree(edata));
7436   return PETSC_SUCCESS;
7437 }
7438 
7439 /*
7440    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7441          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7442 
7443    Collective
7444 
7445    Input Parameter:
7446 .  mat - the matrix
7447 
7448    Notes:
7449      There can be zeros within the blocks
7450 
7451      The blocks can overlap between processes, including laying on more than two processes
7452 
7453 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7454 */
7455 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7456 {
7457   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7458   PetscInt          *diag, *odiag, sc;
7459   VecScatter         scatter;
7460   PetscScalar       *seqv;
7461   const PetscScalar *parv;
7462   const PetscInt    *ia, *ja;
7463   PetscBool          set, flag, done;
7464   Mat                AA = mat, A;
7465   MPI_Comm           comm;
7466   PetscMPIInt        rank, size, tag;
7467   MPI_Status         status;
7468   PetscContainer     container;
7469   EnvelopeData      *edata;
7470   Vec                seq, par;
7471   IS                 isglobal;
7472 
7473   PetscFunctionBegin;
7474   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7475   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7476   if (!set || !flag) {
7477     /* TOO: only needs nonzero structure of transpose */
7478     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7479     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7480   }
7481   PetscCall(MatAIJGetLocalMat(AA, &A));
7482   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7483   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7484 
7485   PetscCall(MatGetLocalSize(mat, &n, NULL));
7486   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7487   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7488   PetscCallMPI(MPI_Comm_size(comm, &size));
7489   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7490 
7491   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7492 
7493   if (rank > 0) {
7494     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7495     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7496   }
7497   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7498   for (i = 0; i < n; i++) {
7499     env = PetscMax(env, ja[ia[i + 1] - 1]);
7500     II  = rstart + i;
7501     if (env == II) {
7502       starts[lblocks]  = tbs;
7503       sizes[lblocks++] = 1 + II - tbs;
7504       tbs              = 1 + II;
7505     }
7506   }
7507   if (rank < size - 1) {
7508     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7509     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7510   }
7511 
7512   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7513   if (!set || !flag) PetscCall(MatDestroy(&AA));
7514   PetscCall(MatDestroy(&A));
7515 
7516   PetscCall(PetscNew(&edata));
7517   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7518   edata->n = lblocks;
7519   /* create IS needed for extracting blocks from the original matrix */
7520   PetscCall(PetscMalloc1(lblocks, &edata->is));
7521   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7522 
7523   /* Create the resulting inverse matrix structure with preallocation information */
7524   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7525   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7526   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7527   PetscCall(MatSetType(edata->C, MATAIJ));
7528 
7529   /* Communicate the start and end of each row, from each block to the correct rank */
7530   /* TODO: Use PetscSF instead of VecScatter */
7531   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7532   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7533   PetscCall(VecGetArrayWrite(seq, &seqv));
7534   for (PetscInt i = 0; i < lblocks; i++) {
7535     for (PetscInt j = 0; j < sizes[i]; j++) {
7536       seqv[cnt]     = starts[i];
7537       seqv[cnt + 1] = starts[i] + sizes[i];
7538       cnt += 2;
7539     }
7540   }
7541   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7542   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7543   sc -= cnt;
7544   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7545   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7546   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7547   PetscCall(ISDestroy(&isglobal));
7548   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7549   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7550   PetscCall(VecScatterDestroy(&scatter));
7551   PetscCall(VecDestroy(&seq));
7552   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7553   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7554   PetscCall(VecGetArrayRead(par, &parv));
7555   cnt = 0;
7556   PetscCall(MatGetSize(mat, NULL, &n));
7557   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7558     PetscInt start, end, d = 0, od = 0;
7559 
7560     start = (PetscInt)PetscRealPart(parv[cnt]);
7561     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7562     cnt += 2;
7563 
7564     if (start < cstart) {
7565       od += cstart - start + n - cend;
7566       d += cend - cstart;
7567     } else if (start < cend) {
7568       od += n - cend;
7569       d += cend - start;
7570     } else od += n - start;
7571     if (end <= cstart) {
7572       od -= cstart - end + n - cend;
7573       d -= cend - cstart;
7574     } else if (end < cend) {
7575       od -= n - cend;
7576       d -= cend - end;
7577     } else od -= n - end;
7578 
7579     odiag[i] = od;
7580     diag[i]  = d;
7581   }
7582   PetscCall(VecRestoreArrayRead(par, &parv));
7583   PetscCall(VecDestroy(&par));
7584   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7585   PetscCall(PetscFree2(diag, odiag));
7586   PetscCall(PetscFree2(sizes, starts));
7587 
7588   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7589   PetscCall(PetscContainerSetPointer(container, edata));
7590   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7591   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7592   PetscCall(PetscObjectDereference((PetscObject)container));
7593   PetscFunctionReturn(PETSC_SUCCESS);
7594 }
7595 
7596 /*@
7597   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7598 
7599   Collective
7600 
7601   Input Parameters:
7602 . A - the matrix
7603 
7604   Output Parameters:
7605 . C - matrix with inverted block diagonal of A.  This matrix should be created and may have its type set.
7606 
7607   Level: advanced
7608 
7609   Note:
7610      For efficiency the matrix A should have all the nonzero entries clustered in smallish blocks along the diagonal.
7611 
7612 .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7613 @*/
7614 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7615 {
7616   PetscContainer   container;
7617   EnvelopeData    *edata;
7618   PetscObjectState nonzerostate;
7619 
7620   PetscFunctionBegin;
7621   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7622   if (!container) {
7623     PetscCall(MatComputeVariableBlockEnvelope(A));
7624     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7625   }
7626   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7627   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7628   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7629   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7630 
7631   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7632   *C = edata->C;
7633 
7634   for (PetscInt i = 0; i < edata->n; i++) {
7635     Mat          D;
7636     PetscScalar *dvalues;
7637 
7638     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7639     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7640     PetscCall(MatSeqDenseInvert(D));
7641     PetscCall(MatDenseGetArray(D, &dvalues));
7642     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7643     PetscCall(MatDestroy(&D));
7644   }
7645   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7646   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7647   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7648   PetscFunctionReturn(PETSC_SUCCESS);
7649 }
7650 
7651 /*@
7652    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7653 
7654    Logically Collective
7655 
7656    Input Parameters:
7657 +  mat - the matrix
7658 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7659 -  bsizes - the block sizes
7660 
7661    Level: intermediate
7662 
7663    Notes:
7664     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7665 
7666     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.
7667 
7668 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7669           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7670 @*/
7671 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7672 {
7673   PetscInt i, ncnt = 0, nlocal;
7674 
7675   PetscFunctionBegin;
7676   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7677   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7678   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7679   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7680   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);
7681   PetscCall(PetscFree(mat->bsizes));
7682   mat->nblocks = nblocks;
7683   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7684   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7685   PetscFunctionReturn(PETSC_SUCCESS);
7686 }
7687 
7688 /*@C
7689    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7690 
7691    Logically Collective; No Fortran Support
7692 
7693    Input Parameter:
7694 .  mat - the matrix
7695 
7696    Output Parameters:
7697 +  nblocks - the number of blocks on this process
7698 -  bsizes - the block sizes
7699 
7700    Level: intermediate
7701 
7702 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7703 @*/
7704 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7705 {
7706   PetscFunctionBegin;
7707   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7708   *nblocks = mat->nblocks;
7709   *bsizes  = mat->bsizes;
7710   PetscFunctionReturn(PETSC_SUCCESS);
7711 }
7712 
7713 /*@
7714    MatSetBlockSizes - Sets the matrix block row and column sizes.
7715 
7716    Logically Collective
7717 
7718    Input Parameters:
7719 +  mat - the matrix
7720 .  rbs - row block size
7721 -  cbs - column block size
7722 
7723    Level: intermediate
7724 
7725    Notes:
7726     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7727     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7728     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7729 
7730     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7731     are compatible with the matrix local sizes.
7732 
7733     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7734 
7735 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7736 @*/
7737 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7738 {
7739   PetscFunctionBegin;
7740   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7741   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7742   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7743   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7744   if (mat->rmap->refcnt) {
7745     ISLocalToGlobalMapping l2g  = NULL;
7746     PetscLayout            nmap = NULL;
7747 
7748     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7749     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7750     PetscCall(PetscLayoutDestroy(&mat->rmap));
7751     mat->rmap          = nmap;
7752     mat->rmap->mapping = l2g;
7753   }
7754   if (mat->cmap->refcnt) {
7755     ISLocalToGlobalMapping l2g  = NULL;
7756     PetscLayout            nmap = NULL;
7757 
7758     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7759     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7760     PetscCall(PetscLayoutDestroy(&mat->cmap));
7761     mat->cmap          = nmap;
7762     mat->cmap->mapping = l2g;
7763   }
7764   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7765   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7766   PetscFunctionReturn(PETSC_SUCCESS);
7767 }
7768 
7769 /*@
7770    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7771 
7772    Logically Collective
7773 
7774    Input Parameters:
7775 +  mat - the matrix
7776 .  fromRow - matrix from which to copy row block size
7777 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7778 
7779    Level: developer
7780 
7781 .seealso: `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7782 @*/
7783 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7784 {
7785   PetscFunctionBegin;
7786   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7787   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7788   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7789   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7790   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7791   PetscFunctionReturn(PETSC_SUCCESS);
7792 }
7793 
7794 /*@
7795    MatResidual - Default routine to calculate the residual r = b - Ax
7796 
7797    Collective
7798 
7799    Input Parameters:
7800 +  mat - the matrix
7801 .  b   - the right-hand-side
7802 -  x   - the approximate solution
7803 
7804    Output Parameter:
7805 .  r - location to store the residual
7806 
7807    Level: developer
7808 
7809 .seealso: `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7810 @*/
7811 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7812 {
7813   PetscFunctionBegin;
7814   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7815   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7816   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7817   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7818   PetscValidType(mat, 1);
7819   MatCheckPreallocated(mat, 1);
7820   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7821   if (!mat->ops->residual) {
7822     PetscCall(MatMult(mat, x, r));
7823     PetscCall(VecAYPX(r, -1.0, b));
7824   } else {
7825     PetscUseTypeMethod(mat, residual, b, x, r);
7826   }
7827   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7828   PetscFunctionReturn(PETSC_SUCCESS);
7829 }
7830 
7831 /*MC
7832     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7833 
7834     Synopsis:
7835     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7836 
7837     Not Collective
7838 
7839     Input Parameters:
7840 +   A - the matrix
7841 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7842 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7843 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7844                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7845                  always used.
7846 
7847     Output Parameters:
7848 +   n - number of local rows in the (possibly compressed) matrix
7849 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7850 .   ja - the column indices
7851 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7852            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7853 
7854     Level: developer
7855 
7856     Note:
7857     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7858 
7859 .seealso: [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7860 M*/
7861 
7862 /*MC
7863     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7864 
7865     Synopsis:
7866     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7867 
7868     Not Collective
7869 
7870     Input Parameters:
7871 +   A - the  matrix
7872 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7873 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7874     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7875                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7876                  always used.
7877 .   n - number of local rows in the (possibly compressed) matrix
7878 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7879 .   ja - the column indices
7880 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7881            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7882 
7883     Level: developer
7884 
7885 .seealso: [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7886 M*/
7887 
7888 /*@C
7889     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7890 
7891    Collective
7892 
7893     Input Parameters:
7894 +   mat - the matrix
7895 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7896 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7897 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicats if the nonzero structure of the
7898                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7899                  always used.
7900 
7901     Output Parameters:
7902 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7903 .   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
7904 .   ja - the column indices, use `NULL` if not needed
7905 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7906            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7907 
7908     Level: developer
7909 
7910     Notes:
7911     You CANNOT change any of the ia[] or ja[] values.
7912 
7913     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7914 
7915     Fortran Notes:
7916     Use
7917 .vb
7918     PetscInt, pointer :: ia(:),ja(:)
7919     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7920     ! Access the ith and jth entries via ia(i) and ja(j)
7921 .ve
7922    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7923 
7924 .seealso: `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7925 @*/
7926 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7927 {
7928   PetscFunctionBegin;
7929   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7930   PetscValidType(mat, 1);
7931   if (n) PetscValidIntPointer(n, 5);
7932   if (ia) PetscValidPointer(ia, 6);
7933   if (ja) PetscValidPointer(ja, 7);
7934   if (done) PetscValidBoolPointer(done, 8);
7935   MatCheckPreallocated(mat, 1);
7936   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7937   else {
7938     if (done) *done = PETSC_TRUE;
7939     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7940     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7941     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7942   }
7943   PetscFunctionReturn(PETSC_SUCCESS);
7944 }
7945 
7946 /*@C
7947     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7948 
7949     Collective
7950 
7951     Input Parameters:
7952 +   mat - the matrix
7953 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7954 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7955                 symmetrized
7956 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7957                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7958                  always used.
7959 .   n - number of columns in the (possibly compressed) matrix
7960 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7961 -   ja - the row indices
7962 
7963     Output Parameters:
7964 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7965 
7966     Level: developer
7967 
7968 .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7969 @*/
7970 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7971 {
7972   PetscFunctionBegin;
7973   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7974   PetscValidType(mat, 1);
7975   PetscValidIntPointer(n, 5);
7976   if (ia) PetscValidPointer(ia, 6);
7977   if (ja) PetscValidPointer(ja, 7);
7978   PetscValidBoolPointer(done, 8);
7979   MatCheckPreallocated(mat, 1);
7980   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7981   else {
7982     *done = PETSC_TRUE;
7983     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7984   }
7985   PetscFunctionReturn(PETSC_SUCCESS);
7986 }
7987 
7988 /*@C
7989     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7990 
7991     Collective
7992 
7993     Input Parameters:
7994 +   mat - the matrix
7995 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7996 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7997 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7998                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7999                  always used.
8000 .   n - size of (possibly compressed) matrix
8001 .   ia - the row pointers
8002 -   ja - the column indices
8003 
8004     Output Parameters:
8005 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8006 
8007     Level: developer
8008 
8009     Note:
8010     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
8011     us of the array after it has been restored. If you pass `NULL`, it will
8012     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
8013 
8014     Fortran Note:
8015    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
8016 .seealso: `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
8017 @*/
8018 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8019 {
8020   PetscFunctionBegin;
8021   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8022   PetscValidType(mat, 1);
8023   if (ia) PetscValidPointer(ia, 6);
8024   if (ja) PetscValidPointer(ja, 7);
8025   if (done) PetscValidBoolPointer(done, 8);
8026   MatCheckPreallocated(mat, 1);
8027 
8028   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8029   else {
8030     if (done) *done = PETSC_TRUE;
8031     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8032     if (n) *n = 0;
8033     if (ia) *ia = NULL;
8034     if (ja) *ja = NULL;
8035   }
8036   PetscFunctionReturn(PETSC_SUCCESS);
8037 }
8038 
8039 /*@C
8040     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8041 
8042     Collective on Mat
8043 
8044     Input Parameters:
8045 +   mat - the matrix
8046 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8047 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8048 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8049                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8050                  always used.
8051 
8052     Output Parameters:
8053 +   n - size of (possibly compressed) matrix
8054 .   ia - the column pointers
8055 .   ja - the row indices
8056 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8057 
8058     Level: developer
8059 
8060 .seealso: `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8061 @*/
8062 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8063 {
8064   PetscFunctionBegin;
8065   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8066   PetscValidType(mat, 1);
8067   if (ia) PetscValidPointer(ia, 6);
8068   if (ja) PetscValidPointer(ja, 7);
8069   PetscValidBoolPointer(done, 8);
8070   MatCheckPreallocated(mat, 1);
8071 
8072   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8073   else {
8074     *done = PETSC_TRUE;
8075     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8076     if (n) *n = 0;
8077     if (ia) *ia = NULL;
8078     if (ja) *ja = NULL;
8079   }
8080   PetscFunctionReturn(PETSC_SUCCESS);
8081 }
8082 
8083 /*@C
8084     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8085 
8086     Collective
8087 
8088     Input Parameters:
8089 +   mat - the matrix
8090 .   ncolors - max color value
8091 .   n   - number of entries in colorarray
8092 -   colorarray - array indicating color for each column
8093 
8094     Output Parameters:
8095 .   iscoloring - coloring generated using colorarray information
8096 
8097     Level: developer
8098 
8099 .seealso: `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8100 @*/
8101 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8102 {
8103   PetscFunctionBegin;
8104   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8105   PetscValidType(mat, 1);
8106   PetscValidIntPointer(colorarray, 4);
8107   PetscValidPointer(iscoloring, 5);
8108   MatCheckPreallocated(mat, 1);
8109 
8110   if (!mat->ops->coloringpatch) {
8111     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8112   } else {
8113     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8114   }
8115   PetscFunctionReturn(PETSC_SUCCESS);
8116 }
8117 
8118 /*@
8119    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8120 
8121    Logically Collective
8122 
8123    Input Parameter:
8124 .  mat - the factored matrix to be reset
8125 
8126    Level: developer
8127 
8128    Notes:
8129    This routine should be used only with factored matrices formed by in-place
8130    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8131    format).  This option can save memory, for example, when solving nonlinear
8132    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8133    ILU(0) preconditioner.
8134 
8135    One can specify in-place ILU(0) factorization by calling
8136 .vb
8137      PCType(pc,PCILU);
8138      PCFactorSeUseInPlace(pc);
8139 .ve
8140    or by using the options -pc_type ilu -pc_factor_in_place
8141 
8142    In-place factorization ILU(0) can also be used as a local
8143    solver for the blocks within the block Jacobi or additive Schwarz
8144    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8145    for details on setting local solver options.
8146 
8147    Most users should employ the `KSP` interface for linear solvers
8148    instead of working directly with matrix algebra routines such as this.
8149    See, e.g., `KSPCreate()`.
8150 
8151 .seealso: `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8152 @*/
8153 PetscErrorCode MatSetUnfactored(Mat mat)
8154 {
8155   PetscFunctionBegin;
8156   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8157   PetscValidType(mat, 1);
8158   MatCheckPreallocated(mat, 1);
8159   mat->factortype = MAT_FACTOR_NONE;
8160   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8161   PetscUseTypeMethod(mat, setunfactored);
8162   PetscFunctionReturn(PETSC_SUCCESS);
8163 }
8164 
8165 /*MC
8166     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8167 
8168     Synopsis:
8169     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8170 
8171     Not collective
8172 
8173     Input Parameter:
8174 .   x - matrix
8175 
8176     Output Parameters:
8177 +   xx_v - the Fortran pointer to the array
8178 -   ierr - error code
8179 
8180     Example of Usage:
8181 .vb
8182       PetscScalar, pointer xx_v(:,:)
8183       ....
8184       call MatDenseGetArrayF90(x,xx_v,ierr)
8185       a = xx_v(3)
8186       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8187 .ve
8188 
8189     Level: advanced
8190 
8191 .seealso: `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8192 M*/
8193 
8194 /*MC
8195     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8196     accessed with `MatDenseGetArrayF90()`.
8197 
8198     Synopsis:
8199     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8200 
8201     Not collective
8202 
8203     Input Parameters:
8204 +   x - matrix
8205 -   xx_v - the Fortran90 pointer to the array
8206 
8207     Output Parameter:
8208 .   ierr - error code
8209 
8210     Example of Usage:
8211 .vb
8212        PetscScalar, pointer xx_v(:,:)
8213        ....
8214        call MatDenseGetArrayF90(x,xx_v,ierr)
8215        a = xx_v(3)
8216        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8217 .ve
8218 
8219     Level: advanced
8220 
8221 .seealso: `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8222 M*/
8223 
8224 /*MC
8225     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8226 
8227     Synopsis:
8228     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8229 
8230     Not collective
8231 
8232     Input Parameter:
8233 .   x - matrix
8234 
8235     Output Parameters:
8236 +   xx_v - the Fortran pointer to the array
8237 -   ierr - error code
8238 
8239     Example of Usage:
8240 .vb
8241       PetscScalar, pointer xx_v(:)
8242       ....
8243       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8244       a = xx_v(3)
8245       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8246 .ve
8247 
8248     Level: advanced
8249 
8250 .seealso: `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8251 M*/
8252 
8253 /*MC
8254     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8255     accessed with `MatSeqAIJGetArrayF90()`.
8256 
8257     Synopsis:
8258     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8259 
8260     Not collective
8261 
8262     Input Parameters:
8263 +   x - matrix
8264 -   xx_v - the Fortran90 pointer to the array
8265 
8266     Output Parameter:
8267 .   ierr - error code
8268 
8269     Example of Usage:
8270 .vb
8271        PetscScalar, pointer xx_v(:)
8272        ....
8273        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8274        a = xx_v(3)
8275        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8276 .ve
8277 
8278     Level: advanced
8279 
8280 .seealso: `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8281 M*/
8282 
8283 /*@
8284     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8285                       as the original matrix.
8286 
8287     Collective
8288 
8289     Input Parameters:
8290 +   mat - the original matrix
8291 .   isrow - parallel IS containing the rows this processor should obtain
8292 .   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.
8293 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8294 
8295     Output Parameter:
8296 .   newmat - the new submatrix, of the same type as the old
8297 
8298     Level: advanced
8299 
8300     Notes:
8301     The submatrix will be able to be multiplied with vectors using the same layout as iscol.
8302 
8303     Some matrix types place restrictions on the row and column indices, such
8304     as that they be sorted or that they be equal to each other. For `MATBAIJ` and `MATSBAIJ` matrices the indices must include all rows/columns of a block;
8305     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8306 
8307     The index sets may not have duplicate entries.
8308 
8309       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8310    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8311    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8312    will reuse the matrix generated the first time.  You should call `MatDestroy()` on newmat when
8313    you are finished using it.
8314 
8315     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8316     the input matrix.
8317 
8318     If iscol is `NULL` then all columns are obtained (not supported in Fortran).
8319 
8320    Example usage:
8321    Consider the following 8x8 matrix with 34 non-zero values, that is
8322    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8323    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8324    as follows:
8325 
8326 .vb
8327             1  2  0  |  0  3  0  |  0  4
8328     Proc0   0  5  6  |  7  0  0  |  8  0
8329             9  0 10  | 11  0  0  | 12  0
8330     -------------------------------------
8331            13  0 14  | 15 16 17  |  0  0
8332     Proc1   0 18  0  | 19 20 21  |  0  0
8333             0  0  0  | 22 23  0  | 24  0
8334     -------------------------------------
8335     Proc2  25 26 27  |  0  0 28  | 29  0
8336            30  0  0  | 31 32 33  |  0 34
8337 .ve
8338 
8339     Suppose isrow = [0 1 | 4 | 6 7] and iscol = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8340 
8341 .vb
8342             2  0  |  0  3  0  |  0
8343     Proc0   5  6  |  7  0  0  |  8
8344     -------------------------------
8345     Proc1  18  0  | 19 20 21  |  0
8346     -------------------------------
8347     Proc2  26 27  |  0  0 28  | 29
8348             0  0  | 31 32 33  |  0
8349 .ve
8350 
8351 .seealso: `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8352 @*/
8353 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8354 {
8355   PetscMPIInt size;
8356   Mat        *local;
8357   IS          iscoltmp;
8358   PetscBool   flg;
8359 
8360   PetscFunctionBegin;
8361   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8362   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8363   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8364   PetscValidPointer(newmat, 5);
8365   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8366   PetscValidType(mat, 1);
8367   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8368   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8369 
8370   MatCheckPreallocated(mat, 1);
8371   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8372 
8373   if (!iscol || isrow == iscol) {
8374     PetscBool   stride;
8375     PetscMPIInt grabentirematrix = 0, grab;
8376     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8377     if (stride) {
8378       PetscInt first, step, n, rstart, rend;
8379       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8380       if (step == 1) {
8381         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8382         if (rstart == first) {
8383           PetscCall(ISGetLocalSize(isrow, &n));
8384           if (n == rend - rstart) grabentirematrix = 1;
8385         }
8386       }
8387     }
8388     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8389     if (grab) {
8390       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8391       if (cll == MAT_INITIAL_MATRIX) {
8392         *newmat = mat;
8393         PetscCall(PetscObjectReference((PetscObject)mat));
8394       }
8395       PetscFunctionReturn(PETSC_SUCCESS);
8396     }
8397   }
8398 
8399   if (!iscol) {
8400     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8401   } else {
8402     iscoltmp = iscol;
8403   }
8404 
8405   /* if original matrix is on just one processor then use submatrix generated */
8406   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8407     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8408     goto setproperties;
8409   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8410     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8411     *newmat = *local;
8412     PetscCall(PetscFree(local));
8413     goto setproperties;
8414   } else if (!mat->ops->createsubmatrix) {
8415     /* Create a new matrix type that implements the operation using the full matrix */
8416     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8417     switch (cll) {
8418     case MAT_INITIAL_MATRIX:
8419       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8420       break;
8421     case MAT_REUSE_MATRIX:
8422       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8423       break;
8424     default:
8425       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8426     }
8427     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8428     goto setproperties;
8429   }
8430 
8431   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8432   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8433   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8434 
8435 setproperties:
8436   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8437   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8438   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8439   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8440   PetscFunctionReturn(PETSC_SUCCESS);
8441 }
8442 
8443 /*@
8444    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8445 
8446    Not Collective
8447 
8448    Input Parameters:
8449 +  A - the matrix we wish to propagate options from
8450 -  B - the matrix we wish to propagate options to
8451 
8452    Level: beginner
8453 
8454    Note:
8455    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8456 
8457 .seealso: `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8458 @*/
8459 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8460 {
8461   PetscFunctionBegin;
8462   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8463   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8464   B->symmetry_eternal            = A->symmetry_eternal;
8465   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8466   B->symmetric                   = A->symmetric;
8467   B->structurally_symmetric      = A->structurally_symmetric;
8468   B->spd                         = A->spd;
8469   B->hermitian                   = A->hermitian;
8470   PetscFunctionReturn(PETSC_SUCCESS);
8471 }
8472 
8473 /*@
8474    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8475    used during the assembly process to store values that belong to
8476    other processors.
8477 
8478    Not Collective
8479 
8480    Input Parameters:
8481 +  mat   - the matrix
8482 .  size  - the initial size of the stash.
8483 -  bsize - the initial size of the block-stash(if used).
8484 
8485    Options Database Keys:
8486 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8487 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8488 
8489    Level: intermediate
8490 
8491    Notes:
8492      The block-stash is used for values set with `MatSetValuesBlocked()` while
8493      the stash is used for values set with `MatSetValues()`
8494 
8495      Run with the option -info and look for output of the form
8496      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8497      to determine the appropriate value, MM, to use for size and
8498      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8499      to determine the value, BMM to use for bsize
8500 
8501 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8502 @*/
8503 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8504 {
8505   PetscFunctionBegin;
8506   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8507   PetscValidType(mat, 1);
8508   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8509   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8510   PetscFunctionReturn(PETSC_SUCCESS);
8511 }
8512 
8513 /*@
8514    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8515      the matrix
8516 
8517    Neighbor-wise Collective
8518 
8519    Input Parameters:
8520 +  mat   - the matrix
8521 .  x,y - the vectors
8522 -  w - where the result is stored
8523 
8524    Level: intermediate
8525 
8526    Notes:
8527     `w` may be the same vector as `y`.
8528 
8529     This allows one to use either the restriction or interpolation (its transpose)
8530     matrix to do the interpolation
8531 
8532 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8533 @*/
8534 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8535 {
8536   PetscInt M, N, Ny;
8537 
8538   PetscFunctionBegin;
8539   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8540   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8541   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8542   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8543   PetscCall(MatGetSize(A, &M, &N));
8544   PetscCall(VecGetSize(y, &Ny));
8545   if (M == Ny) {
8546     PetscCall(MatMultAdd(A, x, y, w));
8547   } else {
8548     PetscCall(MatMultTransposeAdd(A, x, y, w));
8549   }
8550   PetscFunctionReturn(PETSC_SUCCESS);
8551 }
8552 
8553 /*@
8554    MatInterpolate - y = A*x or A'*x depending on the shape of
8555      the matrix
8556 
8557    Neighbor-wise Collective
8558 
8559    Input Parameters:
8560 +  mat   - the matrix
8561 -  x,y - the vectors
8562 
8563    Level: intermediate
8564 
8565    Note:
8566     This allows one to use either the restriction or interpolation (its transpose)
8567     matrix to do the interpolation
8568 
8569 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8570 @*/
8571 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8572 {
8573   PetscInt M, N, Ny;
8574 
8575   PetscFunctionBegin;
8576   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8577   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8578   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8579   PetscCall(MatGetSize(A, &M, &N));
8580   PetscCall(VecGetSize(y, &Ny));
8581   if (M == Ny) {
8582     PetscCall(MatMult(A, x, y));
8583   } else {
8584     PetscCall(MatMultTranspose(A, x, y));
8585   }
8586   PetscFunctionReturn(PETSC_SUCCESS);
8587 }
8588 
8589 /*@
8590    MatRestrict - y = A*x or A'*x
8591 
8592    Neighbor-wise Collective on Mat
8593 
8594    Input Parameters:
8595 +  mat   - the matrix
8596 -  x,y - the vectors
8597 
8598    Level: intermediate
8599 
8600    Note:
8601     This allows one to use either the restriction or interpolation (its transpose)
8602     matrix to do the restriction
8603 
8604 .seealso: `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8605 @*/
8606 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8607 {
8608   PetscInt M, N, Ny;
8609 
8610   PetscFunctionBegin;
8611   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8612   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8613   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8614   PetscCall(MatGetSize(A, &M, &N));
8615   PetscCall(VecGetSize(y, &Ny));
8616   if (M == Ny) {
8617     PetscCall(MatMult(A, x, y));
8618   } else {
8619     PetscCall(MatMultTranspose(A, x, y));
8620   }
8621   PetscFunctionReturn(PETSC_SUCCESS);
8622 }
8623 
8624 /*@
8625    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8626 
8627    Neighbor-wise Collective on Mat
8628 
8629    Input Parameters:
8630 +  mat   - the matrix
8631 -  w, x - the input dense matrices
8632 
8633    Output Parameters:
8634 .  y - the output dense matrix
8635 
8636    Level: intermediate
8637 
8638    Note:
8639     This allows one to use either the restriction or interpolation (its transpose)
8640     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8641     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8642 
8643 .seealso: `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8644 @*/
8645 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8646 {
8647   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8648   PetscBool trans = PETSC_TRUE;
8649   MatReuse  reuse = MAT_INITIAL_MATRIX;
8650 
8651   PetscFunctionBegin;
8652   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8653   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8654   PetscValidType(x, 2);
8655   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8656   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8657   PetscCall(MatGetSize(A, &M, &N));
8658   PetscCall(MatGetSize(x, &Mx, &Nx));
8659   if (N == Mx) trans = PETSC_FALSE;
8660   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);
8661   Mo = trans ? N : M;
8662   if (*y) {
8663     PetscCall(MatGetSize(*y, &My, &Ny));
8664     if (Mo == My && Nx == Ny) {
8665       reuse = MAT_REUSE_MATRIX;
8666     } else {
8667       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);
8668       PetscCall(MatDestroy(y));
8669     }
8670   }
8671 
8672   if (w && *y == w) { /* this is to minimize changes in PCMG */
8673     PetscBool flg;
8674 
8675     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8676     if (w) {
8677       PetscInt My, Ny, Mw, Nw;
8678 
8679       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8680       PetscCall(MatGetSize(*y, &My, &Ny));
8681       PetscCall(MatGetSize(w, &Mw, &Nw));
8682       if (!flg || My != Mw || Ny != Nw) w = NULL;
8683     }
8684     if (!w) {
8685       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8686       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8687       PetscCall(PetscObjectDereference((PetscObject)w));
8688     } else {
8689       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8690     }
8691   }
8692   if (!trans) {
8693     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8694   } else {
8695     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8696   }
8697   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8698   PetscFunctionReturn(PETSC_SUCCESS);
8699 }
8700 
8701 /*@
8702    MatMatInterpolate - Y = A*X or A'*X
8703 
8704    Neighbor-wise Collective on Mat
8705 
8706    Input Parameters:
8707 +  mat   - the matrix
8708 -  x - the input dense matrix
8709 
8710    Output Parameters:
8711 .  y - the output dense matrix
8712 
8713    Level: intermediate
8714 
8715    Note:
8716     This allows one to use either the restriction or interpolation (its transpose)
8717     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8718     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8719 
8720 .seealso: `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8721 @*/
8722 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8723 {
8724   PetscFunctionBegin;
8725   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8726   PetscFunctionReturn(PETSC_SUCCESS);
8727 }
8728 
8729 /*@
8730    MatMatRestrict - Y = A*X or A'*X
8731 
8732    Neighbor-wise Collective on Mat
8733 
8734    Input Parameters:
8735 +  mat   - the matrix
8736 -  x - the input dense matrix
8737 
8738    Output Parameters:
8739 .  y - the output dense matrix
8740 
8741    Level: intermediate
8742 
8743    Note:
8744     This allows one to use either the restriction or interpolation (its transpose)
8745     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8746     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8747 
8748 .seealso: `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8749 @*/
8750 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8751 {
8752   PetscFunctionBegin;
8753   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8754   PetscFunctionReturn(PETSC_SUCCESS);
8755 }
8756 
8757 /*@
8758    MatGetNullSpace - retrieves the null space of a matrix.
8759 
8760    Logically Collective
8761 
8762    Input Parameters:
8763 +  mat - the matrix
8764 -  nullsp - the null space object
8765 
8766    Level: developer
8767 
8768 .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8769 @*/
8770 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8771 {
8772   PetscFunctionBegin;
8773   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8774   PetscValidPointer(nullsp, 2);
8775   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8776   PetscFunctionReturn(PETSC_SUCCESS);
8777 }
8778 
8779 /*@
8780    MatSetNullSpace - attaches a null space to a matrix.
8781 
8782    Logically Collective
8783 
8784    Input Parameters:
8785 +  mat - the matrix
8786 -  nullsp - the null space object
8787 
8788    Level: advanced
8789 
8790    Notes:
8791       This null space is used by the `KSP` linear solvers to solve singular systems.
8792 
8793       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`
8794 
8795       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
8796       to zero but the linear system will still be solved in a least squares sense.
8797 
8798       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8799    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).
8800    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
8801    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
8802    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).
8803    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8804 
8805     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8806     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8807     routine also automatically calls `MatSetTransposeNullSpace()`.
8808 
8809     The user should call `MatNullSpaceDestroy()`.
8810 
8811 .seealso: `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8812           `KSPSetPCSide()`
8813 @*/
8814 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8815 {
8816   PetscFunctionBegin;
8817   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8818   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8819   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8820   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8821   mat->nullsp = nullsp;
8822   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8823   PetscFunctionReturn(PETSC_SUCCESS);
8824 }
8825 
8826 /*@
8827    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8828 
8829    Logically Collective
8830 
8831    Input Parameters:
8832 +  mat - the matrix
8833 -  nullsp - the null space object
8834 
8835    Level: developer
8836 
8837 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8838 @*/
8839 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8840 {
8841   PetscFunctionBegin;
8842   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8843   PetscValidType(mat, 1);
8844   PetscValidPointer(nullsp, 2);
8845   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8846   PetscFunctionReturn(PETSC_SUCCESS);
8847 }
8848 
8849 /*@
8850    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8851 
8852    Logically Collective
8853 
8854    Input Parameters:
8855 +  mat - the matrix
8856 -  nullsp - the null space object
8857 
8858    Level: advanced
8859 
8860    Notes:
8861    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8862 
8863    See `MatSetNullSpace()`
8864 
8865 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8866 @*/
8867 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8868 {
8869   PetscFunctionBegin;
8870   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8871   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8872   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8873   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8874   mat->transnullsp = nullsp;
8875   PetscFunctionReturn(PETSC_SUCCESS);
8876 }
8877 
8878 /*@
8879    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8880         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8881 
8882    Logically Collective
8883 
8884    Input Parameters:
8885 +  mat - the matrix
8886 -  nullsp - the null space object
8887 
8888    Level: advanced
8889 
8890    Notes:
8891    Overwrites any previous near null space that may have been attached
8892 
8893    You can remove the null space by calling this routine with an nullsp of `NULL`
8894 
8895 .seealso: `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8896 @*/
8897 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8898 {
8899   PetscFunctionBegin;
8900   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8901   PetscValidType(mat, 1);
8902   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8903   MatCheckPreallocated(mat, 1);
8904   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8905   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8906   mat->nearnullsp = nullsp;
8907   PetscFunctionReturn(PETSC_SUCCESS);
8908 }
8909 
8910 /*@
8911    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8912 
8913    Not Collective
8914 
8915    Input Parameter:
8916 .  mat - the matrix
8917 
8918    Output Parameter:
8919 .  nullsp - the null space object, `NULL` if not set
8920 
8921    Level: advanced
8922 
8923 .seealso: `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8924 @*/
8925 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8926 {
8927   PetscFunctionBegin;
8928   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8929   PetscValidType(mat, 1);
8930   PetscValidPointer(nullsp, 2);
8931   MatCheckPreallocated(mat, 1);
8932   *nullsp = mat->nearnullsp;
8933   PetscFunctionReturn(PETSC_SUCCESS);
8934 }
8935 
8936 /*@C
8937    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8938 
8939    Collective
8940 
8941    Input Parameters:
8942 +  mat - the matrix
8943 .  row - row/column permutation
8944 .  fill - expected fill factor >= 1.0
8945 -  level - level of fill, for ICC(k)
8946 
8947    Notes:
8948    Probably really in-place only when level of fill is zero, otherwise allocates
8949    new space to store factored matrix and deletes previous memory.
8950 
8951    Most users should employ the `KSP` interface for linear solvers
8952    instead of working directly with matrix algebra routines such as this.
8953    See, e.g., `KSPCreate()`.
8954 
8955    Level: developer
8956 
8957    Developer Note:
8958    The Fortran interface is not autogenerated as the
8959    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8960 
8961 .seealso: `Mat`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8962 @*/
8963 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8964 {
8965   PetscFunctionBegin;
8966   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8967   PetscValidType(mat, 1);
8968   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8969   PetscValidPointer(info, 3);
8970   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8971   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8972   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8973   MatCheckPreallocated(mat, 1);
8974   PetscUseTypeMethod(mat, iccfactor, row, info);
8975   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8976   PetscFunctionReturn(PETSC_SUCCESS);
8977 }
8978 
8979 /*@
8980    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8981          ghosted ones.
8982 
8983    Not Collective
8984 
8985    Input Parameters:
8986 +  mat - the matrix
8987 -  diag - the diagonal values, including ghost ones
8988 
8989    Level: developer
8990 
8991    Notes:
8992     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8993 
8994     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8995 
8996 .seealso: `Mat`, `MatDiagonalScale()`
8997 @*/
8998 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8999 {
9000   PetscMPIInt size;
9001 
9002   PetscFunctionBegin;
9003   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9004   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
9005   PetscValidType(mat, 1);
9006 
9007   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
9008   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
9009   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
9010   if (size == 1) {
9011     PetscInt n, m;
9012     PetscCall(VecGetSize(diag, &n));
9013     PetscCall(MatGetSize(mat, NULL, &m));
9014     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9015     PetscCall(MatDiagonalScale(mat, NULL, diag));
9016   } else {
9017     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9018   }
9019   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9020   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9021   PetscFunctionReturn(PETSC_SUCCESS);
9022 }
9023 
9024 /*@
9025    MatGetInertia - Gets the inertia from a factored matrix
9026 
9027    Collective
9028 
9029    Input Parameter:
9030 .  mat - the matrix
9031 
9032    Output Parameters:
9033 +   nneg - number of negative eigenvalues
9034 .   nzero - number of zero eigenvalues
9035 -   npos - number of positive eigenvalues
9036 
9037    Level: advanced
9038 
9039    Note:
9040     Matrix must have been factored by `MatCholeskyFactor()`
9041 
9042 .seealso: `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9043 @*/
9044 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9045 {
9046   PetscFunctionBegin;
9047   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9048   PetscValidType(mat, 1);
9049   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9050   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9051   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9052   PetscFunctionReturn(PETSC_SUCCESS);
9053 }
9054 
9055 /*@C
9056    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9057 
9058    Neighbor-wise Collective
9059 
9060    Input Parameters:
9061 +  mat - the factored matrix obtained with `MatGetFactor()`
9062 -  b - the right-hand-side vectors
9063 
9064    Output Parameter:
9065 .  x - the result vectors
9066 
9067    Level: developer
9068 
9069    Note:
9070    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9071    call `MatSolves`(A,x,x).
9072 
9073 .seealso: `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9074 @*/
9075 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9076 {
9077   PetscFunctionBegin;
9078   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9079   PetscValidType(mat, 1);
9080   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9081   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9082   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9083 
9084   MatCheckPreallocated(mat, 1);
9085   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9086   PetscUseTypeMethod(mat, solves, b, x);
9087   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9088   PetscFunctionReturn(PETSC_SUCCESS);
9089 }
9090 
9091 /*@
9092    MatIsSymmetric - Test whether a matrix is symmetric
9093 
9094    Collective
9095 
9096    Input Parameters:
9097 +  A - the matrix to test
9098 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9099 
9100    Output Parameters:
9101 .  flg - the result
9102 
9103    Level: intermediate
9104 
9105    Notes:
9106     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9107 
9108     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9109 
9110     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9111     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9112 
9113 .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9114           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9115 @*/
9116 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9117 {
9118   PetscFunctionBegin;
9119   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9120   PetscValidBoolPointer(flg, 3);
9121 
9122   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9123   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9124   else {
9125     if (!A->ops->issymmetric) {
9126       MatType mattype;
9127       PetscCall(MatGetType(A, &mattype));
9128       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for symmetric", mattype);
9129     }
9130     PetscUseTypeMethod(A, issymmetric, tol, flg);
9131     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9132   }
9133   PetscFunctionReturn(PETSC_SUCCESS);
9134 }
9135 
9136 /*@
9137    MatIsHermitian - Test whether a matrix is Hermitian
9138 
9139    Collective on Mat
9140 
9141    Input Parameters:
9142 +  A - the matrix to test
9143 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9144 
9145    Output Parameters:
9146 .  flg - the result
9147 
9148    Level: intermediate
9149 
9150    Notes:
9151     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9152 
9153     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9154 
9155     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9156     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9157 
9158 .seealso: `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9159           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9160 @*/
9161 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9162 {
9163   PetscFunctionBegin;
9164   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9165   PetscValidBoolPointer(flg, 3);
9166 
9167   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9168   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9169   else {
9170     if (!A->ops->ishermitian) {
9171       MatType mattype;
9172       PetscCall(MatGetType(A, &mattype));
9173       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for hermitian", mattype);
9174     }
9175     PetscUseTypeMethod(A, ishermitian, tol, flg);
9176     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9177   }
9178   PetscFunctionReturn(PETSC_SUCCESS);
9179 }
9180 
9181 /*@
9182    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9183 
9184    Not Collective
9185 
9186    Input Parameter:
9187 .  A - the matrix to check
9188 
9189    Output Parameters:
9190 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9191 -  flg - the result (only valid if set is `PETSC_TRUE`)
9192 
9193    Level: advanced
9194 
9195    Notes:
9196    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9197    if you want it explicitly checked
9198 
9199     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9200     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9201 
9202 .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9203 @*/
9204 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9205 {
9206   PetscFunctionBegin;
9207   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9208   PetscValidBoolPointer(set, 2);
9209   PetscValidBoolPointer(flg, 3);
9210   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9211     *set = PETSC_TRUE;
9212     *flg = PetscBool3ToBool(A->symmetric);
9213   } else {
9214     *set = PETSC_FALSE;
9215   }
9216   PetscFunctionReturn(PETSC_SUCCESS);
9217 }
9218 
9219 /*@
9220    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9221 
9222    Not Collective
9223 
9224    Input Parameter:
9225 .  A - the matrix to check
9226 
9227    Output Parameters:
9228 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9229 -  flg - the result (only valid if set is `PETSC_TRUE`)
9230 
9231    Level: advanced
9232 
9233    Notes:
9234    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9235 
9236    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9237    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9238 
9239 .seealso: `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9240 @*/
9241 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9242 {
9243   PetscFunctionBegin;
9244   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9245   PetscValidBoolPointer(set, 2);
9246   PetscValidBoolPointer(flg, 3);
9247   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9248     *set = PETSC_TRUE;
9249     *flg = PetscBool3ToBool(A->spd);
9250   } else {
9251     *set = PETSC_FALSE;
9252   }
9253   PetscFunctionReturn(PETSC_SUCCESS);
9254 }
9255 
9256 /*@
9257    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9258 
9259    Not Collective
9260 
9261    Input Parameter:
9262 .  A - the matrix to check
9263 
9264    Output Parameters:
9265 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9266 -  flg - the result (only valid if set is `PETSC_TRUE`)
9267 
9268    Level: advanced
9269 
9270    Notes:
9271    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9272    if you want it explicitly checked
9273 
9274    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9275    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9276 
9277 .seealso: `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9278 @*/
9279 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9280 {
9281   PetscFunctionBegin;
9282   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9283   PetscValidBoolPointer(set, 2);
9284   PetscValidBoolPointer(flg, 3);
9285   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9286     *set = PETSC_TRUE;
9287     *flg = PetscBool3ToBool(A->hermitian);
9288   } else {
9289     *set = PETSC_FALSE;
9290   }
9291   PetscFunctionReturn(PETSC_SUCCESS);
9292 }
9293 
9294 /*@
9295    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9296 
9297    Collective on Mat
9298 
9299    Input Parameter:
9300 .  A - the matrix to test
9301 
9302    Output Parameters:
9303 .  flg - the result
9304 
9305    Level: intermediate
9306 
9307    Notes:
9308    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9309 
9310    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
9311    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9312 
9313 .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9314 @*/
9315 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9316 {
9317   PetscFunctionBegin;
9318   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9319   PetscValidBoolPointer(flg, 2);
9320   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9321     *flg = PetscBool3ToBool(A->structurally_symmetric);
9322   } else {
9323     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9324     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9325   }
9326   PetscFunctionReturn(PETSC_SUCCESS);
9327 }
9328 
9329 /*@
9330    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9331 
9332    Not Collective
9333 
9334    Input Parameter:
9335 .  A - the matrix to check
9336 
9337    Output Parameters:
9338 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9339 -  flg - the result (only valid if set is PETSC_TRUE)
9340 
9341    Level: advanced
9342 
9343    Notes:
9344    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
9345    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9346 
9347    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9348 
9349 .seealso: `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9350 @*/
9351 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9352 {
9353   PetscFunctionBegin;
9354   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9355   PetscValidBoolPointer(set, 2);
9356   PetscValidBoolPointer(flg, 3);
9357   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9358     *set = PETSC_TRUE;
9359     *flg = PetscBool3ToBool(A->structurally_symmetric);
9360   } else {
9361     *set = PETSC_FALSE;
9362   }
9363   PetscFunctionReturn(PETSC_SUCCESS);
9364 }
9365 
9366 /*@
9367    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9368        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9369 
9370     Not collective
9371 
9372    Input Parameter:
9373 .   mat - the matrix
9374 
9375    Output Parameters:
9376 +   nstash   - the size of the stash
9377 .   reallocs - the number of additional mallocs incurred.
9378 .   bnstash   - the size of the block stash
9379 -   breallocs - the number of additional mallocs incurred.in the block stash
9380 
9381    Level: advanced
9382 
9383 .seealso: `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9384 @*/
9385 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9386 {
9387   PetscFunctionBegin;
9388   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9389   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9390   PetscFunctionReturn(PETSC_SUCCESS);
9391 }
9392 
9393 /*@C
9394    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9395    parallel layout, `PetscLayout` for rows and columns
9396 
9397    Collective
9398 
9399    Input Parameter:
9400 .  mat - the matrix
9401 
9402    Output Parameters:
9403 +   right - (optional) vector that the matrix can be multiplied against
9404 -   left - (optional) vector that the matrix vector product can be stored in
9405 
9406   Level: advanced
9407 
9408    Notes:
9409     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()`.
9410 
9411     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9412 
9413 .seealso: `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9414 @*/
9415 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9416 {
9417   PetscFunctionBegin;
9418   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9419   PetscValidType(mat, 1);
9420   if (mat->ops->getvecs) {
9421     PetscUseTypeMethod(mat, getvecs, right, left);
9422   } else {
9423     PetscInt rbs, cbs;
9424     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9425     if (right) {
9426       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9427       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9428       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9429       PetscCall(VecSetBlockSize(*right, cbs));
9430       PetscCall(VecSetType(*right, mat->defaultvectype));
9431 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9432       if (mat->boundtocpu && mat->bindingpropagates) {
9433         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9434         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9435       }
9436 #endif
9437       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9438     }
9439     if (left) {
9440       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9441       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9442       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9443       PetscCall(VecSetBlockSize(*left, rbs));
9444       PetscCall(VecSetType(*left, mat->defaultvectype));
9445 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9446       if (mat->boundtocpu && mat->bindingpropagates) {
9447         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9448         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9449       }
9450 #endif
9451       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9452     }
9453   }
9454   PetscFunctionReturn(PETSC_SUCCESS);
9455 }
9456 
9457 /*@C
9458    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9459      with default values.
9460 
9461    Not Collective
9462 
9463    Input Parameters:
9464 .    info - the `MatFactorInfo` data structure
9465 
9466    Level: developer
9467 
9468    Notes:
9469     The solvers are generally used through the `KSP` and `PC` objects, for example
9470           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9471 
9472     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9473 
9474    Developer Note:
9475    The Fortran interface is not autogenerated as the
9476    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9477 
9478 .seealso: `Mat`, `MatGetFactor()`, `MatFactorInfo`
9479 @*/
9480 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9481 {
9482   PetscFunctionBegin;
9483   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9484   PetscFunctionReturn(PETSC_SUCCESS);
9485 }
9486 
9487 /*@
9488    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9489 
9490    Collective
9491 
9492    Input Parameters:
9493 +  mat - the factored matrix
9494 -  is - the index set defining the Schur indices (0-based)
9495 
9496    Level: advanced
9497 
9498    Notes:
9499     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9500 
9501    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9502 
9503    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9504 
9505 .seealso: `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9506           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9507 @*/
9508 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9509 {
9510   PetscErrorCode (*f)(Mat, IS);
9511 
9512   PetscFunctionBegin;
9513   PetscValidType(mat, 1);
9514   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9515   PetscValidType(is, 2);
9516   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9517   PetscCheckSameComm(mat, 1, is, 2);
9518   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9519   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9520   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9521   PetscCall(MatDestroy(&mat->schur));
9522   PetscCall((*f)(mat, is));
9523   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9524   PetscFunctionReturn(PETSC_SUCCESS);
9525 }
9526 
9527 /*@
9528   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9529 
9530    Logically Collective
9531 
9532    Input Parameters:
9533 +  F - the factored matrix obtained by calling `MatGetFactor()`
9534 .  S - location where to return the Schur complement, can be `NULL`
9535 -  status - the status of the Schur complement matrix, can be `NULL`
9536 
9537    Level: advanced
9538 
9539    Notes:
9540    You must call `MatFactorSetSchurIS()` before calling this routine.
9541 
9542    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9543 
9544    The routine provides a copy of the Schur matrix stored within the solver data structures.
9545    The caller must destroy the object when it is no longer needed.
9546    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9547 
9548    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)
9549 
9550    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9551 
9552    Developer Note:
9553     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9554    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9555 
9556 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9557 @*/
9558 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9559 {
9560   PetscFunctionBegin;
9561   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9562   if (S) PetscValidPointer(S, 2);
9563   if (status) PetscValidPointer(status, 3);
9564   if (S) {
9565     PetscErrorCode (*f)(Mat, Mat *);
9566 
9567     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9568     if (f) {
9569       PetscCall((*f)(F, S));
9570     } else {
9571       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9572     }
9573   }
9574   if (status) *status = F->schur_status;
9575   PetscFunctionReturn(PETSC_SUCCESS);
9576 }
9577 
9578 /*@
9579   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9580 
9581    Logically Collective
9582 
9583    Input Parameters:
9584 +  F - the factored matrix obtained by calling `MatGetFactor()`
9585 .  *S - location where to return the Schur complement, can be `NULL`
9586 -  status - the status of the Schur complement matrix, can be `NULL`
9587 
9588    Level: advanced
9589 
9590    Notes:
9591    You must call `MatFactorSetSchurIS()` before calling this routine.
9592 
9593    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9594 
9595    The routine returns a the Schur Complement stored within the data structures of the solver.
9596 
9597    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9598 
9599    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9600 
9601    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9602 
9603    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9604 
9605 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9606 @*/
9607 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9608 {
9609   PetscFunctionBegin;
9610   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9611   if (S) PetscValidPointer(S, 2);
9612   if (status) PetscValidPointer(status, 3);
9613   if (S) *S = F->schur;
9614   if (status) *status = F->schur_status;
9615   PetscFunctionReturn(PETSC_SUCCESS);
9616 }
9617 
9618 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9619 {
9620   Mat S = F->schur;
9621 
9622   PetscFunctionBegin;
9623   switch (F->schur_status) {
9624   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9625   case MAT_FACTOR_SCHUR_INVERTED:
9626     if (S) {
9627       S->ops->solve             = NULL;
9628       S->ops->matsolve          = NULL;
9629       S->ops->solvetranspose    = NULL;
9630       S->ops->matsolvetranspose = NULL;
9631       S->ops->solveadd          = NULL;
9632       S->ops->solvetransposeadd = NULL;
9633       S->factortype             = MAT_FACTOR_NONE;
9634       PetscCall(PetscFree(S->solvertype));
9635     }
9636   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9637     break;
9638   default:
9639     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9640   }
9641   PetscFunctionReturn(PETSC_SUCCESS);
9642 }
9643 
9644 /*@
9645   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9646 
9647    Logically Collective
9648 
9649    Input Parameters:
9650 +  F - the factored matrix obtained by calling `MatGetFactor()`
9651 .  *S - location where the Schur complement is stored
9652 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9653 
9654    Level: advanced
9655 
9656 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9657 @*/
9658 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9659 {
9660   PetscFunctionBegin;
9661   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9662   if (S) {
9663     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9664     *S = NULL;
9665   }
9666   F->schur_status = status;
9667   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9668   PetscFunctionReturn(PETSC_SUCCESS);
9669 }
9670 
9671 /*@
9672   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9673 
9674    Logically Collective
9675 
9676    Input Parameters:
9677 +  F - the factored matrix obtained by calling `MatGetFactor()`
9678 .  rhs - location where the right hand side of the Schur complement system is stored
9679 -  sol - location where the solution of the Schur complement system has to be returned
9680 
9681    Level: advanced
9682 
9683    Notes:
9684    The sizes of the vectors should match the size of the Schur complement
9685 
9686    Must be called after `MatFactorSetSchurIS()`
9687 
9688 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9689 @*/
9690 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9691 {
9692   PetscFunctionBegin;
9693   PetscValidType(F, 1);
9694   PetscValidType(rhs, 2);
9695   PetscValidType(sol, 3);
9696   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9697   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9698   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9699   PetscCheckSameComm(F, 1, rhs, 2);
9700   PetscCheckSameComm(F, 1, sol, 3);
9701   PetscCall(MatFactorFactorizeSchurComplement(F));
9702   switch (F->schur_status) {
9703   case MAT_FACTOR_SCHUR_FACTORED:
9704     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9705     break;
9706   case MAT_FACTOR_SCHUR_INVERTED:
9707     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9708     break;
9709   default:
9710     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9711   }
9712   PetscFunctionReturn(PETSC_SUCCESS);
9713 }
9714 
9715 /*@
9716   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9717 
9718    Logically Collective
9719 
9720    Input Parameters:
9721 +  F - the factored matrix obtained by calling `MatGetFactor()`
9722 .  rhs - location where the right hand side of the Schur complement system is stored
9723 -  sol - location where the solution of the Schur complement system has to be returned
9724 
9725    Level: advanced
9726 
9727    Notes:
9728    The sizes of the vectors should match the size of the Schur complement
9729 
9730    Must be called after `MatFactorSetSchurIS()`
9731 
9732 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9733 @*/
9734 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9735 {
9736   PetscFunctionBegin;
9737   PetscValidType(F, 1);
9738   PetscValidType(rhs, 2);
9739   PetscValidType(sol, 3);
9740   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9741   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9742   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9743   PetscCheckSameComm(F, 1, rhs, 2);
9744   PetscCheckSameComm(F, 1, sol, 3);
9745   PetscCall(MatFactorFactorizeSchurComplement(F));
9746   switch (F->schur_status) {
9747   case MAT_FACTOR_SCHUR_FACTORED:
9748     PetscCall(MatSolve(F->schur, rhs, sol));
9749     break;
9750   case MAT_FACTOR_SCHUR_INVERTED:
9751     PetscCall(MatMult(F->schur, rhs, sol));
9752     break;
9753   default:
9754     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9755   }
9756   PetscFunctionReturn(PETSC_SUCCESS);
9757 }
9758 
9759 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9760 #if PetscDefined(HAVE_CUDA)
9761 PETSC_EXTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Private(Mat);
9762 #endif
9763 
9764 /* Schur status updated in the interface */
9765 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9766 {
9767   Mat S = F->schur;
9768 
9769   PetscFunctionBegin;
9770   if (S) {
9771     PetscMPIInt size;
9772     PetscBool   isdense, isdensecuda;
9773 
9774     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9775     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9776     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9777     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9778     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9779     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9780     if (isdense) {
9781       PetscCall(MatSeqDenseInvertFactors_Private(S));
9782     } else if (isdensecuda) {
9783 #if defined(PETSC_HAVE_CUDA)
9784       PetscCall(MatSeqDenseCUDAInvertFactors_Private(S));
9785 #endif
9786     }
9787     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9788   }
9789   PetscFunctionReturn(PETSC_SUCCESS);
9790 }
9791 
9792 /*@
9793   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9794 
9795    Logically Collective on F
9796 
9797    Input Parameters:
9798 .  F - the factored matrix obtained by calling `MatGetFactor()`
9799 
9800    Level: advanced
9801 
9802    Notes:
9803     Must be called after `MatFactorSetSchurIS()`.
9804 
9805    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9806 
9807 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9808 @*/
9809 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9810 {
9811   PetscFunctionBegin;
9812   PetscValidType(F, 1);
9813   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9814   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9815   PetscCall(MatFactorFactorizeSchurComplement(F));
9816   PetscCall(MatFactorInvertSchurComplement_Private(F));
9817   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9818   PetscFunctionReturn(PETSC_SUCCESS);
9819 }
9820 
9821 /*@
9822   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9823 
9824    Logically Collective
9825 
9826    Input Parameters:
9827 .  F - the factored matrix obtained by calling `MatGetFactor()`
9828 
9829    Level: advanced
9830 
9831    Note:
9832     Must be called after `MatFactorSetSchurIS()`
9833 
9834 .seealso: `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9835 @*/
9836 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9837 {
9838   MatFactorInfo info;
9839 
9840   PetscFunctionBegin;
9841   PetscValidType(F, 1);
9842   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9843   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9844   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9845   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9846     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9847   } else {
9848     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9849   }
9850   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9851   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9852   PetscFunctionReturn(PETSC_SUCCESS);
9853 }
9854 
9855 /*@
9856    MatPtAP - Creates the matrix product C = P^T * A * P
9857 
9858    Neighbor-wise Collective
9859 
9860    Input Parameters:
9861 +  A - the matrix
9862 .  P - the projection matrix
9863 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9864 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9865           if the result is a dense matrix this is irrelevant
9866 
9867    Output Parameters:
9868 .  C - the product matrix
9869 
9870    Level: intermediate
9871 
9872    Notes:
9873    C will be created and must be destroyed by the user with `MatDestroy()`.
9874 
9875    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9876 
9877    Developer Note:
9878    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9879 
9880 .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9881 @*/
9882 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9883 {
9884   PetscFunctionBegin;
9885   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9886   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9887 
9888   if (scall == MAT_INITIAL_MATRIX) {
9889     PetscCall(MatProductCreate(A, P, NULL, C));
9890     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9891     PetscCall(MatProductSetAlgorithm(*C, "default"));
9892     PetscCall(MatProductSetFill(*C, fill));
9893 
9894     (*C)->product->api_user = PETSC_TRUE;
9895     PetscCall(MatProductSetFromOptions(*C));
9896     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);
9897     PetscCall(MatProductSymbolic(*C));
9898   } else { /* scall == MAT_REUSE_MATRIX */
9899     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9900   }
9901 
9902   PetscCall(MatProductNumeric(*C));
9903   (*C)->symmetric = A->symmetric;
9904   (*C)->spd       = A->spd;
9905   PetscFunctionReturn(PETSC_SUCCESS);
9906 }
9907 
9908 /*@
9909    MatRARt - Creates the matrix product C = R * A * R^T
9910 
9911    Neighbor-wise Collective
9912 
9913    Input Parameters:
9914 +  A - the matrix
9915 .  R - the projection matrix
9916 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9917 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9918           if the result is a dense matrix this is irrelevant
9919 
9920    Output Parameters:
9921 .  C - the product matrix
9922 
9923    Level: intermediate
9924 
9925    Notes:
9926    C will be created and must be destroyed by the user with `MatDestroy()`.
9927 
9928    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9929 
9930    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9931    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9932    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9933    We recommend using MatPtAP().
9934 
9935 .seealso: `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9936 @*/
9937 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9938 {
9939   PetscFunctionBegin;
9940   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9941   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9942 
9943   if (scall == MAT_INITIAL_MATRIX) {
9944     PetscCall(MatProductCreate(A, R, NULL, C));
9945     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9946     PetscCall(MatProductSetAlgorithm(*C, "default"));
9947     PetscCall(MatProductSetFill(*C, fill));
9948 
9949     (*C)->product->api_user = PETSC_TRUE;
9950     PetscCall(MatProductSetFromOptions(*C));
9951     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);
9952     PetscCall(MatProductSymbolic(*C));
9953   } else { /* scall == MAT_REUSE_MATRIX */
9954     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9955   }
9956 
9957   PetscCall(MatProductNumeric(*C));
9958   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9959   PetscFunctionReturn(PETSC_SUCCESS);
9960 }
9961 
9962 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9963 {
9964   PetscFunctionBegin;
9965   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9966 
9967   if (scall == MAT_INITIAL_MATRIX) {
9968     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9969     PetscCall(MatProductCreate(A, B, NULL, C));
9970     PetscCall(MatProductSetType(*C, ptype));
9971     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9972     PetscCall(MatProductSetFill(*C, fill));
9973 
9974     (*C)->product->api_user = PETSC_TRUE;
9975     PetscCall(MatProductSetFromOptions(*C));
9976     PetscCall(MatProductSymbolic(*C));
9977   } else { /* scall == MAT_REUSE_MATRIX */
9978     Mat_Product *product = (*C)->product;
9979     PetscBool    isdense;
9980 
9981     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9982     if (isdense && product && product->type != ptype) {
9983       PetscCall(MatProductClear(*C));
9984       product = NULL;
9985     }
9986     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9987     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9988       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9989       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9990       product           = (*C)->product;
9991       product->fill     = fill;
9992       product->api_user = PETSC_TRUE;
9993       product->clear    = PETSC_TRUE;
9994 
9995       PetscCall(MatProductSetType(*C, ptype));
9996       PetscCall(MatProductSetFromOptions(*C));
9997       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);
9998       PetscCall(MatProductSymbolic(*C));
9999     } else { /* user may change input matrices A or B when REUSE */
10000       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
10001     }
10002   }
10003   PetscCall(MatProductNumeric(*C));
10004   PetscFunctionReturn(PETSC_SUCCESS);
10005 }
10006 
10007 /*@
10008    MatMatMult - Performs matrix-matrix multiplication C=A*B.
10009 
10010    Neighbor-wise Collective
10011 
10012    Input Parameters:
10013 +  A - the left matrix
10014 .  B - the right matrix
10015 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10016 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
10017           if the result is a dense matrix this is irrelevant
10018 
10019    Output Parameters:
10020 .  C - the product matrix
10021 
10022    Notes:
10023    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10024 
10025    `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
10026    call to this function with `MAT_INITIAL_MATRIX`.
10027 
10028    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10029 
10030    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`,
10031    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10032 
10033    Example of Usage:
10034 .vb
10035      MatProductCreate(A,B,NULL,&C);
10036      MatProductSetType(C,MATPRODUCT_AB);
10037      MatProductSymbolic(C);
10038      MatProductNumeric(C); // compute C=A * B
10039      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10040      MatProductNumeric(C);
10041      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10042      MatProductNumeric(C);
10043 .ve
10044 
10045    Level: intermediate
10046 
10047 .seealso: `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10048 @*/
10049 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10050 {
10051   PetscFunctionBegin;
10052   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10053   PetscFunctionReturn(PETSC_SUCCESS);
10054 }
10055 
10056 /*@
10057    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10058 
10059    Neighbor-wise Collective
10060 
10061    Input Parameters:
10062 +  A - the left matrix
10063 .  B - the right matrix
10064 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10065 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10066 
10067    Output Parameters:
10068 .  C - the product matrix
10069 
10070    Level: intermediate
10071 
10072    Notes:
10073    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10074 
10075    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10076 
10077    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10078    actually needed.
10079 
10080    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10081    and for pairs of `MATMPIDENSE` matrices.
10082 
10083    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10084 
10085    Options Database Keys:
10086 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10087               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10088               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10089 
10090 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10091 @*/
10092 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10093 {
10094   PetscFunctionBegin;
10095   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10096   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10097   PetscFunctionReturn(PETSC_SUCCESS);
10098 }
10099 
10100 /*@
10101    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10102 
10103    Neighbor-wise Collective
10104 
10105    Input Parameters:
10106 +  A - the left matrix
10107 .  B - the right matrix
10108 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10109 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10110 
10111    Output Parameters:
10112 .  C - the product matrix
10113 
10114    Level: intermediate
10115 
10116    Notes:
10117    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10118 
10119    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10120 
10121    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10122 
10123    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10124    actually needed.
10125 
10126    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10127    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10128 
10129 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10130 @*/
10131 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10132 {
10133   PetscFunctionBegin;
10134   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10135   PetscFunctionReturn(PETSC_SUCCESS);
10136 }
10137 
10138 /*@
10139    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10140 
10141    Neighbor-wise Collective
10142 
10143    Input Parameters:
10144 +  A - the left matrix
10145 .  B - the middle matrix
10146 .  C - the right matrix
10147 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10148 -  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
10149           if the result is a dense matrix this is irrelevant
10150 
10151    Output Parameters:
10152 .  D - the product matrix
10153 
10154    Level: intermediate
10155 
10156    Notes:
10157    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10158 
10159    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10160 
10161    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10162 
10163    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10164    actually needed.
10165 
10166    If you have many matrices with the same non-zero structure to multiply, you
10167    should use `MAT_REUSE_MATRIX` in all calls but the first
10168 
10169 .seealso: `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10170 @*/
10171 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10172 {
10173   PetscFunctionBegin;
10174   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10175   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10176 
10177   if (scall == MAT_INITIAL_MATRIX) {
10178     PetscCall(MatProductCreate(A, B, C, D));
10179     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10180     PetscCall(MatProductSetAlgorithm(*D, "default"));
10181     PetscCall(MatProductSetFill(*D, fill));
10182 
10183     (*D)->product->api_user = PETSC_TRUE;
10184     PetscCall(MatProductSetFromOptions(*D));
10185     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,
10186                ((PetscObject)C)->type_name);
10187     PetscCall(MatProductSymbolic(*D));
10188   } else { /* user may change input matrices when REUSE */
10189     PetscCall(MatProductReplaceMats(A, B, C, *D));
10190   }
10191   PetscCall(MatProductNumeric(*D));
10192   PetscFunctionReturn(PETSC_SUCCESS);
10193 }
10194 
10195 /*@
10196    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10197 
10198    Collective
10199 
10200    Input Parameters:
10201 +  mat - the matrix
10202 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10203 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10204 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10205 
10206    Output Parameter:
10207 .  matredundant - redundant matrix
10208 
10209    Level: advanced
10210 
10211    Notes:
10212    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10213    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10214 
10215    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10216    calling it.
10217 
10218    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10219 
10220 .seealso: `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10221 @*/
10222 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10223 {
10224   MPI_Comm       comm;
10225   PetscMPIInt    size;
10226   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10227   Mat_Redundant *redund     = NULL;
10228   PetscSubcomm   psubcomm   = NULL;
10229   MPI_Comm       subcomm_in = subcomm;
10230   Mat           *matseq;
10231   IS             isrow, iscol;
10232   PetscBool      newsubcomm = PETSC_FALSE;
10233 
10234   PetscFunctionBegin;
10235   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10236   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10237     PetscValidPointer(*matredundant, 5);
10238     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10239   }
10240 
10241   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10242   if (size == 1 || nsubcomm == 1) {
10243     if (reuse == MAT_INITIAL_MATRIX) {
10244       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10245     } else {
10246       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");
10247       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10248     }
10249     PetscFunctionReturn(PETSC_SUCCESS);
10250   }
10251 
10252   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10253   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10254   MatCheckPreallocated(mat, 1);
10255 
10256   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10257   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10258     /* create psubcomm, then get subcomm */
10259     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10260     PetscCallMPI(MPI_Comm_size(comm, &size));
10261     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10262 
10263     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10264     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10265     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10266     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10267     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10268     newsubcomm = PETSC_TRUE;
10269     PetscCall(PetscSubcommDestroy(&psubcomm));
10270   }
10271 
10272   /* get isrow, iscol and a local sequential matrix matseq[0] */
10273   if (reuse == MAT_INITIAL_MATRIX) {
10274     mloc_sub = PETSC_DECIDE;
10275     nloc_sub = PETSC_DECIDE;
10276     if (bs < 1) {
10277       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10278       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10279     } else {
10280       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10281       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10282     }
10283     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10284     rstart = rend - mloc_sub;
10285     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10286     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10287   } else { /* reuse == MAT_REUSE_MATRIX */
10288     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");
10289     /* retrieve subcomm */
10290     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10291     redund = (*matredundant)->redundant;
10292     isrow  = redund->isrow;
10293     iscol  = redund->iscol;
10294     matseq = redund->matseq;
10295   }
10296   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10297 
10298   /* get matredundant over subcomm */
10299   if (reuse == MAT_INITIAL_MATRIX) {
10300     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10301 
10302     /* create a supporting struct and attach it to C for reuse */
10303     PetscCall(PetscNew(&redund));
10304     (*matredundant)->redundant = redund;
10305     redund->isrow              = isrow;
10306     redund->iscol              = iscol;
10307     redund->matseq             = matseq;
10308     if (newsubcomm) {
10309       redund->subcomm = subcomm;
10310     } else {
10311       redund->subcomm = MPI_COMM_NULL;
10312     }
10313   } else {
10314     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10315   }
10316 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10317   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10318     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10319     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10320   }
10321 #endif
10322   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10323   PetscFunctionReturn(PETSC_SUCCESS);
10324 }
10325 
10326 /*@C
10327    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10328    a given `Mat`. Each submatrix can span multiple procs.
10329 
10330    Collective
10331 
10332    Input Parameters:
10333 +  mat - the matrix
10334 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10335 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10336 
10337    Output Parameter:
10338 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10339 
10340   Level: advanced
10341 
10342   Notes:
10343   The submatrix partition across processors is dictated by `subComm` a
10344   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10345   is not restricted to be grouped with consecutive original ranks.
10346 
10347   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10348   map directly to the layout of the original matrix [wrt the local
10349   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10350   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10351   the `subMat`. However the offDiagMat looses some columns - and this is
10352   reconstructed with `MatSetValues()`
10353 
10354   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10355 
10356 .seealso: `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10357 @*/
10358 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10359 {
10360   PetscMPIInt commsize, subCommSize;
10361 
10362   PetscFunctionBegin;
10363   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10364   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10365   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10366 
10367   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");
10368   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10369   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10370   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10371   PetscFunctionReturn(PETSC_SUCCESS);
10372 }
10373 
10374 /*@
10375    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10376 
10377    Not Collective
10378 
10379    Input Parameters:
10380 +  mat - matrix to extract local submatrix from
10381 .  isrow - local row indices for submatrix
10382 -  iscol - local column indices for submatrix
10383 
10384    Output Parameter:
10385 .  submat - the submatrix
10386 
10387    Level: intermediate
10388 
10389    Notes:
10390    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10391 
10392    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10393    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10394 
10395    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10396    `MatSetValuesBlockedLocal()` will also be implemented.
10397 
10398    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10399    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10400 
10401 .seealso: `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10402 @*/
10403 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10404 {
10405   PetscFunctionBegin;
10406   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10407   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10408   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10409   PetscCheckSameComm(isrow, 2, iscol, 3);
10410   PetscValidPointer(submat, 4);
10411   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10412 
10413   if (mat->ops->getlocalsubmatrix) {
10414     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10415   } else {
10416     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10417   }
10418   PetscFunctionReturn(PETSC_SUCCESS);
10419 }
10420 
10421 /*@
10422    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10423 
10424    Not Collective
10425 
10426    Input Parameters:
10427 +  mat - matrix to extract local submatrix from
10428 .  isrow - local row indices for submatrix
10429 .  iscol - local column indices for submatrix
10430 -  submat - the submatrix
10431 
10432    Level: intermediate
10433 
10434 .seealso: `Mat`, `MatGetLocalSubMatrix()`
10435 @*/
10436 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10437 {
10438   PetscFunctionBegin;
10439   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10440   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10441   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10442   PetscCheckSameComm(isrow, 2, iscol, 3);
10443   PetscValidPointer(submat, 4);
10444   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10445 
10446   if (mat->ops->restorelocalsubmatrix) {
10447     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10448   } else {
10449     PetscCall(MatDestroy(submat));
10450   }
10451   *submat = NULL;
10452   PetscFunctionReturn(PETSC_SUCCESS);
10453 }
10454 
10455 /*@
10456    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10457 
10458    Collective
10459 
10460    Input Parameter:
10461 .  mat - the matrix
10462 
10463    Output Parameter:
10464 .  is - if any rows have zero diagonals this contains the list of them
10465 
10466    Level: developer
10467 
10468 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10469 @*/
10470 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10471 {
10472   PetscFunctionBegin;
10473   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10474   PetscValidType(mat, 1);
10475   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10476   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10477 
10478   if (!mat->ops->findzerodiagonals) {
10479     Vec                diag;
10480     const PetscScalar *a;
10481     PetscInt          *rows;
10482     PetscInt           rStart, rEnd, r, nrow = 0;
10483 
10484     PetscCall(MatCreateVecs(mat, &diag, NULL));
10485     PetscCall(MatGetDiagonal(mat, diag));
10486     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10487     PetscCall(VecGetArrayRead(diag, &a));
10488     for (r = 0; r < rEnd - rStart; ++r)
10489       if (a[r] == 0.0) ++nrow;
10490     PetscCall(PetscMalloc1(nrow, &rows));
10491     nrow = 0;
10492     for (r = 0; r < rEnd - rStart; ++r)
10493       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10494     PetscCall(VecRestoreArrayRead(diag, &a));
10495     PetscCall(VecDestroy(&diag));
10496     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10497   } else {
10498     PetscUseTypeMethod(mat, findzerodiagonals, is);
10499   }
10500   PetscFunctionReturn(PETSC_SUCCESS);
10501 }
10502 
10503 /*@
10504    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10505 
10506    Collective
10507 
10508    Input Parameter:
10509 .  mat - the matrix
10510 
10511    Output Parameter:
10512 .  is - contains the list of rows with off block diagonal entries
10513 
10514    Level: developer
10515 
10516 .seealso: `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10517 @*/
10518 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10519 {
10520   PetscFunctionBegin;
10521   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10522   PetscValidType(mat, 1);
10523   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10524   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10525 
10526   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10527   PetscFunctionReturn(PETSC_SUCCESS);
10528 }
10529 
10530 /*@C
10531   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10532 
10533   Collective; No Fortran Support
10534 
10535   Input Parameters:
10536 . mat - the matrix
10537 
10538   Output Parameters:
10539 . values - the block inverses in column major order (FORTRAN-like)
10540 
10541   Level: advanced
10542 
10543    Notes:
10544    The size of the blocks is determined by the block size of the matrix.
10545 
10546    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10547 
10548    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10549 
10550 .seealso: `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10551 @*/
10552 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10553 {
10554   PetscFunctionBegin;
10555   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10556   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10557   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10558   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10559   PetscFunctionReturn(PETSC_SUCCESS);
10560 }
10561 
10562 /*@C
10563   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10564 
10565   Collective; No Fortran Support
10566 
10567   Input Parameters:
10568 + mat - the matrix
10569 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10570 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10571 
10572   Output Parameters:
10573 . values - the block inverses in column major order (FORTRAN-like)
10574 
10575   Level: advanced
10576 
10577   Notes:
10578   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10579 
10580   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10581 
10582 .seealso: `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10583 @*/
10584 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10585 {
10586   PetscFunctionBegin;
10587   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10588   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10589   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10590   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10591   PetscFunctionReturn(PETSC_SUCCESS);
10592 }
10593 
10594 /*@
10595   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10596 
10597   Collective on Mat
10598 
10599   Input Parameters:
10600 + A - the matrix
10601 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10602 
10603   Level: advanced
10604 
10605   Note:
10606   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10607 
10608 .seealso: `Mat`, `MatInvertBlockDiagonal()`
10609 @*/
10610 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10611 {
10612   const PetscScalar *vals;
10613   PetscInt          *dnnz;
10614   PetscInt           m, rstart, rend, bs, i, j;
10615 
10616   PetscFunctionBegin;
10617   PetscCall(MatInvertBlockDiagonal(A, &vals));
10618   PetscCall(MatGetBlockSize(A, &bs));
10619   PetscCall(MatGetLocalSize(A, &m, NULL));
10620   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10621   PetscCall(PetscMalloc1(m / bs, &dnnz));
10622   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10623   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10624   PetscCall(PetscFree(dnnz));
10625   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10626   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10627   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10628   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10629   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10630   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10631   PetscFunctionReturn(PETSC_SUCCESS);
10632 }
10633 
10634 /*@C
10635     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10636     via `MatTransposeColoringCreate()`.
10637 
10638     Collective on c
10639 
10640     Input Parameter:
10641 .   c - coloring context
10642 
10643     Level: intermediate
10644 
10645 .seealso: `Mat`, `MatTransposeColoringCreate()`
10646 @*/
10647 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10648 {
10649   MatTransposeColoring matcolor = *c;
10650 
10651   PetscFunctionBegin;
10652   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10653   if (--((PetscObject)matcolor)->refct > 0) {
10654     matcolor = NULL;
10655     PetscFunctionReturn(PETSC_SUCCESS);
10656   }
10657 
10658   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10659   PetscCall(PetscFree(matcolor->rows));
10660   PetscCall(PetscFree(matcolor->den2sp));
10661   PetscCall(PetscFree(matcolor->colorforcol));
10662   PetscCall(PetscFree(matcolor->columns));
10663   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10664   PetscCall(PetscHeaderDestroy(c));
10665   PetscFunctionReturn(PETSC_SUCCESS);
10666 }
10667 
10668 /*@C
10669     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10670     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10671     `MatTransposeColoring` to sparse B.
10672 
10673     Collective on coloring
10674 
10675     Input Parameters:
10676 +   B - sparse matrix B
10677 .   Btdense - symbolic dense matrix B^T
10678 -   coloring - coloring context created with `MatTransposeColoringCreate()`
10679 
10680     Output Parameter:
10681 .   Btdense - dense matrix B^T
10682 
10683     Level: developer
10684 
10685     Note:
10686     These are used internally for some implementations of `MatRARt()`
10687 
10688 .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10689 @*/
10690 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10691 {
10692   PetscFunctionBegin;
10693   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10694   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10695   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10696 
10697   PetscCall((B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10698   PetscFunctionReturn(PETSC_SUCCESS);
10699 }
10700 
10701 /*@C
10702     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10703     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10704     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10705     Csp from Cden.
10706 
10707     Collective
10708 
10709     Input Parameters:
10710 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10711 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10712 
10713     Output Parameter:
10714 .   Csp - sparse matrix
10715 
10716     Level: developer
10717 
10718     Note:
10719     These are used internally for some implementations of `MatRARt()`
10720 
10721 .seealso: `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10722 @*/
10723 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10724 {
10725   PetscFunctionBegin;
10726   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10727   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10728   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10729 
10730   PetscCall((Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10731   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10732   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10733   PetscFunctionReturn(PETSC_SUCCESS);
10734 }
10735 
10736 /*@C
10737    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10738 
10739    Collective
10740 
10741    Input Parameters:
10742 +  mat - the matrix product C
10743 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10744 
10745     Output Parameter:
10746 .   color - the new coloring context
10747 
10748     Level: intermediate
10749 
10750 .seealso: `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10751           `MatTransColoringApplyDenToSp()`
10752 @*/
10753 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10754 {
10755   MatTransposeColoring c;
10756   MPI_Comm             comm;
10757 
10758   PetscFunctionBegin;
10759   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10760   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10761   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10762 
10763   c->ctype = iscoloring->ctype;
10764   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10765 
10766   *color = c;
10767   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10768   PetscFunctionReturn(PETSC_SUCCESS);
10769 }
10770 
10771 /*@
10772       MatGetNonzeroState - Returns a 64 bit integer representing the current state of nonzeros in the matrix. If the
10773         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10774         same, otherwise it will be larger
10775 
10776      Not Collective
10777 
10778   Input Parameter:
10779 .    A  - the matrix
10780 
10781   Output Parameter:
10782 .    state - the current state
10783 
10784   Level: intermediate
10785 
10786   Notes:
10787     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10788          different matrices
10789 
10790     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10791 
10792     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10793 
10794 .seealso: `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10795 @*/
10796 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10797 {
10798   PetscFunctionBegin;
10799   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10800   *state = mat->nonzerostate;
10801   PetscFunctionReturn(PETSC_SUCCESS);
10802 }
10803 
10804 /*@
10805       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10806                  matrices from each processor
10807 
10808     Collective
10809 
10810    Input Parameters:
10811 +    comm - the communicators the parallel matrix will live on
10812 .    seqmat - the input sequential matrices
10813 .    n - number of local columns (or `PETSC_DECIDE`)
10814 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10815 
10816    Output Parameter:
10817 .    mpimat - the parallel matrix generated
10818 
10819     Level: developer
10820 
10821    Note:
10822     The number of columns of the matrix in EACH processor MUST be the same.
10823 
10824 .seealso: `Mat`
10825 @*/
10826 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10827 {
10828   PetscMPIInt size;
10829 
10830   PetscFunctionBegin;
10831   PetscCallMPI(MPI_Comm_size(comm, &size));
10832   if (size == 1) {
10833     if (reuse == MAT_INITIAL_MATRIX) {
10834       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10835     } else {
10836       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10837     }
10838     PetscFunctionReturn(PETSC_SUCCESS);
10839   }
10840 
10841   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");
10842 
10843   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10844   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10845   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10846   PetscFunctionReturn(PETSC_SUCCESS);
10847 }
10848 
10849 /*@
10850      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10851 
10852     Collective
10853 
10854    Input Parameters:
10855 +    A   - the matrix to create subdomains from
10856 -    N   - requested number of subdomains
10857 
10858    Output Parameters:
10859 +    n   - number of subdomains resulting on this rank
10860 -    iss - `IS` list with indices of subdomains on this rank
10861 
10862     Level: advanced
10863 
10864     Note:
10865     The number of subdomains must be smaller than the communicator size
10866 
10867 .seealso: `Mat`, `IS`
10868 @*/
10869 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10870 {
10871   MPI_Comm    comm, subcomm;
10872   PetscMPIInt size, rank, color;
10873   PetscInt    rstart, rend, k;
10874 
10875   PetscFunctionBegin;
10876   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10877   PetscCallMPI(MPI_Comm_size(comm, &size));
10878   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10879   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);
10880   *n    = 1;
10881   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10882   color = rank / k;
10883   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10884   PetscCall(PetscMalloc1(1, iss));
10885   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10886   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10887   PetscCallMPI(MPI_Comm_free(&subcomm));
10888   PetscFunctionReturn(PETSC_SUCCESS);
10889 }
10890 
10891 /*@
10892    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10893 
10894    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10895    If they are not the same, uses `MatMatMatMult()`.
10896 
10897    Once the coarse grid problem is constructed, correct for interpolation operators
10898    that are not of full rank, which can legitimately happen in the case of non-nested
10899    geometric multigrid.
10900 
10901    Input Parameters:
10902 +  restrct - restriction operator
10903 .  dA - fine grid matrix
10904 .  interpolate - interpolation operator
10905 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10906 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10907 
10908    Output Parameters:
10909 .  A - the Galerkin coarse matrix
10910 
10911    Options Database Key:
10912 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10913 
10914    Level: developer
10915 
10916 .seealso: `Mat`, `MatPtAP()`, `MatMatMatMult()`
10917 @*/
10918 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10919 {
10920   IS  zerorows;
10921   Vec diag;
10922 
10923   PetscFunctionBegin;
10924   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10925   /* Construct the coarse grid matrix */
10926   if (interpolate == restrct) {
10927     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10928   } else {
10929     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10930   }
10931 
10932   /* If the interpolation matrix is not of full rank, A will have zero rows.
10933      This can legitimately happen in the case of non-nested geometric multigrid.
10934      In that event, we set the rows of the matrix to the rows of the identity,
10935      ignoring the equations (as the RHS will also be zero). */
10936 
10937   PetscCall(MatFindZeroRows(*A, &zerorows));
10938 
10939   if (zerorows != NULL) { /* if there are any zero rows */
10940     PetscCall(MatCreateVecs(*A, &diag, NULL));
10941     PetscCall(MatGetDiagonal(*A, diag));
10942     PetscCall(VecISSet(diag, zerorows, 1.0));
10943     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10944     PetscCall(VecDestroy(&diag));
10945     PetscCall(ISDestroy(&zerorows));
10946   }
10947   PetscFunctionReturn(PETSC_SUCCESS);
10948 }
10949 
10950 /*@C
10951     MatSetOperation - Allows user to set a matrix operation for any matrix type
10952 
10953    Logically Collective
10954 
10955     Input Parameters:
10956 +   mat - the matrix
10957 .   op - the name of the operation
10958 -   f - the function that provides the operation
10959 
10960    Level: developer
10961 
10962     Usage:
10963 .vb
10964   extern PetscErrorCode usermult(Mat, Vec, Vec);
10965 
10966   PetscCall(MatCreateXXX(comm, ..., &A));
10967   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10968 .ve
10969 
10970     Notes:
10971     See the file `include/petscmat.h` for a complete list of matrix
10972     operations, which all have the form MATOP_<OPERATION>, where
10973     <OPERATION> is the name (in all capital letters) of the
10974     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10975 
10976     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10977     sequence as the usual matrix interface routines, since they
10978     are intended to be accessed via the usual matrix interface
10979     routines, e.g.,
10980 .vb
10981   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10982 .ve
10983 
10984     In particular each function MUST return `PETSC_SUCCESS` on success and
10985     nonzero on failure.
10986 
10987     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10988 
10989 .seealso: `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10990 @*/
10991 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10992 {
10993   PetscFunctionBegin;
10994   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10995   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10996   (((void (**)(void))mat->ops)[op]) = f;
10997   PetscFunctionReturn(PETSC_SUCCESS);
10998 }
10999 
11000 /*@C
11001     MatGetOperation - Gets a matrix operation for any matrix type.
11002 
11003     Not Collective
11004 
11005     Input Parameters:
11006 +   mat - the matrix
11007 -   op - the name of the operation
11008 
11009     Output Parameter:
11010 .   f - the function that provides the operation
11011 
11012     Level: developer
11013 
11014     Usage:
11015 $      PetscErrorCode (*usermult)(Mat,Vec,Vec);
11016 $      MatGetOperation(A,MATOP_MULT,(void(**)(void))&usermult);
11017 
11018     Notes:
11019     See the file include/petscmat.h for a complete list of matrix
11020     operations, which all have the form MATOP_<OPERATION>, where
11021     <OPERATION> is the name (in all capital letters) of the
11022     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11023 
11024     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11025 
11026 .seealso: `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11027 @*/
11028 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11029 {
11030   PetscFunctionBegin;
11031   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11032   *f = (((void (**)(void))mat->ops)[op]);
11033   PetscFunctionReturn(PETSC_SUCCESS);
11034 }
11035 
11036 /*@
11037     MatHasOperation - Determines whether the given matrix supports the particular operation.
11038 
11039    Not Collective
11040 
11041    Input Parameters:
11042 +  mat - the matrix
11043 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11044 
11045    Output Parameter:
11046 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11047 
11048    Level: advanced
11049 
11050    Note:
11051    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11052 
11053 .seealso: `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11054 @*/
11055 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11056 {
11057   PetscFunctionBegin;
11058   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11059   PetscValidBoolPointer(has, 3);
11060   if (mat->ops->hasoperation) {
11061     PetscUseTypeMethod(mat, hasoperation, op, has);
11062   } else {
11063     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11064     else {
11065       *has = PETSC_FALSE;
11066       if (op == MATOP_CREATE_SUBMATRIX) {
11067         PetscMPIInt size;
11068 
11069         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11070         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11071       }
11072     }
11073   }
11074   PetscFunctionReturn(PETSC_SUCCESS);
11075 }
11076 
11077 /*@
11078     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11079 
11080    Collective
11081 
11082    Input Parameters:
11083 .  mat - the matrix
11084 
11085    Output Parameter:
11086 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11087 
11088    Level: beginner
11089 
11090 .seealso: `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11091 @*/
11092 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11093 {
11094   PetscFunctionBegin;
11095   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11096   PetscValidType(mat, 1);
11097   PetscValidBoolPointer(cong, 2);
11098   if (!mat->rmap || !mat->cmap) {
11099     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11100     PetscFunctionReturn(PETSC_SUCCESS);
11101   }
11102   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11103     PetscCall(PetscLayoutSetUp(mat->rmap));
11104     PetscCall(PetscLayoutSetUp(mat->cmap));
11105     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11106     if (*cong) mat->congruentlayouts = 1;
11107     else mat->congruentlayouts = 0;
11108   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11109   PetscFunctionReturn(PETSC_SUCCESS);
11110 }
11111 
11112 PetscErrorCode MatSetInf(Mat A)
11113 {
11114   PetscFunctionBegin;
11115   PetscUseTypeMethod(A, setinf);
11116   PetscFunctionReturn(PETSC_SUCCESS);
11117 }
11118 
11119 /*@C
11120    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
11121    and possibly removes small values from the graph structure.
11122 
11123    Collective
11124 
11125    Input Parameters:
11126 +  A - the matrix
11127 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11128 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11129 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11130 
11131    Output Parameter:
11132 .  graph - the resulting graph
11133 
11134    Level: advanced
11135 
11136 .seealso: `Mat`, `MatCreate()`, `PCGAMG`
11137 @*/
11138 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11139 {
11140   PetscFunctionBegin;
11141   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11142   PetscValidType(A, 1);
11143   PetscValidLogicalCollectiveBool(A, scale, 3);
11144   PetscValidPointer(graph, 5);
11145   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11146   PetscFunctionReturn(PETSC_SUCCESS);
11147 }
11148 
11149 /*@
11150   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11151   meaning the same memory is used for the matrix, and no new memory is allocated.
11152 
11153   Collective on mat
11154 
11155   Input Parameter:
11156 . A - the matrix
11157 
11158   Output Parameter:
11159 . A - the matrix
11160 
11161   Level: intermediate
11162 
11163 .seealso: `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11164 @*/
11165 PetscErrorCode MatEliminateZeros(Mat A)
11166 {
11167   PetscFunctionBegin;
11168   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11169   PetscUseTypeMethod(A, eliminatezeros);
11170   PetscFunctionReturn(PETSC_SUCCESS);
11171 }
11172