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