xref: /petsc/src/mat/interface/matrix.c (revision 2d1571503b53ddc44d5587ea811639ee03673e35)
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_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_Getsymtransreduced, MAT_GetBrowsOfAcols;
34 PetscLogEvent MAT_GetBrowsOfAocols, MAT_Getlocalmat, MAT_Getlocalmatcondensed, MAT_Seqstompi, MAT_Seqstompinum, MAT_Seqstompisym;
35 PetscLogEvent MAT_GetMultiProcBlock;
36 PetscLogEvent MAT_CUSPARSECopyToGPU, MAT_CUSPARSECopyFromGPU, MAT_CUSPARSEGenerateTranspose, MAT_CUSPARSESolveAnalysis;
37 PetscLogEvent MAT_HIPSPARSECopyToGPU, MAT_HIPSPARSECopyFromGPU, MAT_HIPSPARSEGenerateTranspose, MAT_HIPSPARSESolveAnalysis;
38 PetscLogEvent MAT_PreallCOO, MAT_SetVCOO;
39 PetscLogEvent MAT_SetValuesBatch;
40 PetscLogEvent MAT_ViennaCLCopyToGPU;
41 PetscLogEvent MAT_CUDACopyToGPU;
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    Example:
61 .vb
62      PetscRandomCreate(PETSC_COMM_WORLD,&rctx);
63      MatSetRandom(x,rctx);
64      PetscRandomDestroy(rctx);
65 .ve
66 
67    Level: intermediate
68 
69    Notes:
70    For sparse matrices that have been preallocated but not been assembled it randomly selects appropriate locations,
71 
72    for sparse matrices that already have locations it fills the locations with random numbers.
73 
74    It generates an error if used on sparse matrices that have not been preallocated.
75 
76 .seealso: [](chapter_matrices), `Mat`, `PetscRandom`, `PetscRandomCreate()`, `MatZeroEntries()`, `MatSetValues()`, `PetscRandomCreate()`, `PetscRandomDestroy()`
77 @*/
78 PetscErrorCode MatSetRandom(Mat x, PetscRandom rctx)
79 {
80   PetscRandom randObj = NULL;
81 
82   PetscFunctionBegin;
83   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
84   if (rctx) PetscValidHeaderSpecific(rctx, PETSC_RANDOM_CLASSID, 2);
85   PetscValidType(x, 1);
86   MatCheckPreallocated(x, 1);
87 
88   if (!rctx) {
89     MPI_Comm comm;
90     PetscCall(PetscObjectGetComm((PetscObject)x, &comm));
91     PetscCall(PetscRandomCreate(comm, &randObj));
92     PetscCall(PetscRandomSetType(randObj, x->defaultrandtype));
93     PetscCall(PetscRandomSetFromOptions(randObj));
94     rctx = randObj;
95   }
96   PetscCall(PetscLogEventBegin(MAT_SetRandom, x, rctx, 0, 0));
97   PetscUseTypeMethod(x, setrandom, rctx);
98   PetscCall(PetscLogEventEnd(MAT_SetRandom, x, rctx, 0, 0));
99 
100   PetscCall(MatAssemblyBegin(x, MAT_FINAL_ASSEMBLY));
101   PetscCall(MatAssemblyEnd(x, MAT_FINAL_ASSEMBLY));
102   PetscCall(PetscRandomDestroy(&randObj));
103   PetscFunctionReturn(PETSC_SUCCESS);
104 }
105 
106 /*@
107    MatFactorGetErrorZeroPivot - returns the pivot value that was determined to be zero and the row it occurred in
108 
109    Logically Collective
110 
111    Input Parameter:
112 .  mat - the factored matrix
113 
114    Output Parameters:
115 +  pivot - the pivot value computed
116 -  row - the row that the zero pivot occurred. This row value must be interpreted carefully due to row reorderings and which processes
117          the share the matrix
118 
119    Level: advanced
120 
121    Notes:
122     This routine does not work for factorizations done with external packages.
123 
124     This routine should only be called if `MatGetFactorError()` returns a value of `MAT_FACTOR_NUMERIC_ZEROPIVOT`
125 
126     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
127 
128 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`,
129           `MAT_FACTOR_NUMERIC_ZEROPIVOT`
130 @*/
131 PetscErrorCode MatFactorGetErrorZeroPivot(Mat mat, PetscReal *pivot, PetscInt *row)
132 {
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
135   PetscValidRealPointer(pivot, 2);
136   PetscValidIntPointer(row, 3);
137   *pivot = mat->factorerror_zeropivot_value;
138   *row   = mat->factorerror_zeropivot_row;
139   PetscFunctionReturn(PETSC_SUCCESS);
140 }
141 
142 /*@
143    MatFactorGetError - gets the error code from a factorization
144 
145    Logically Collective
146 
147    Input Parameter:
148 .  mat - the factored matrix
149 
150    Output Parameter:
151 .  err  - the error code
152 
153    Level: advanced
154 
155    Note:
156     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
157 
158 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`,
159           `MatFactorClearError()`, `MatFactorGetErrorZeroPivot()`, `MatFactorError`
160 @*/
161 PetscErrorCode MatFactorGetError(Mat mat, MatFactorError *err)
162 {
163   PetscFunctionBegin;
164   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
165   PetscValidPointer(err, 2);
166   *err = mat->factorerrortype;
167   PetscFunctionReturn(PETSC_SUCCESS);
168 }
169 
170 /*@
171    MatFactorClearError - clears the error code in a factorization
172 
173    Logically Collective
174 
175    Input Parameter:
176 .  mat - the factored matrix
177 
178    Level: developer
179 
180    Note:
181     This can also be called on non-factored matrices that come from, for example, matrices used in SOR.
182 
183 .seealso: [](chapter_matrices), `Mat`, `MatZeroEntries()`, `MatFactor()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`, `MatFactorGetError()`, `MatFactorGetErrorZeroPivot()`,
184           `MatGetErrorCode()`, `MatFactorError`
185 @*/
186 PetscErrorCode MatFactorClearError(Mat mat)
187 {
188   PetscFunctionBegin;
189   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
190   mat->factorerrortype             = MAT_FACTOR_NOERROR;
191   mat->factorerror_zeropivot_value = 0.0;
192   mat->factorerror_zeropivot_row   = 0;
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 PETSC_INTERN PetscErrorCode MatFindNonzeroRowsOrCols_Basic(Mat mat, PetscBool cols, PetscReal tol, IS *nonzero)
197 {
198   Vec                r, l;
199   const PetscScalar *al;
200   PetscInt           i, nz, gnz, N, n;
201 
202   PetscFunctionBegin;
203   PetscCall(MatCreateVecs(mat, &r, &l));
204   if (!cols) { /* nonzero rows */
205     PetscCall(MatGetSize(mat, &N, NULL));
206     PetscCall(MatGetLocalSize(mat, &n, NULL));
207     PetscCall(VecSet(l, 0.0));
208     PetscCall(VecSetRandom(r, NULL));
209     PetscCall(MatMult(mat, r, l));
210     PetscCall(VecGetArrayRead(l, &al));
211   } else { /* nonzero columns */
212     PetscCall(MatGetSize(mat, NULL, &N));
213     PetscCall(MatGetLocalSize(mat, NULL, &n));
214     PetscCall(VecSet(r, 0.0));
215     PetscCall(VecSetRandom(l, NULL));
216     PetscCall(MatMultTranspose(mat, l, r));
217     PetscCall(VecGetArrayRead(r, &al));
218   }
219   if (tol <= 0.0) {
220     for (i = 0, nz = 0; i < n; i++)
221       if (al[i] != 0.0) nz++;
222   } else {
223     for (i = 0, nz = 0; i < n; i++)
224       if (PetscAbsScalar(al[i]) > tol) nz++;
225   }
226   PetscCall(MPIU_Allreduce(&nz, &gnz, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
227   if (gnz != N) {
228     PetscInt *nzr;
229     PetscCall(PetscMalloc1(nz, &nzr));
230     if (nz) {
231       if (tol < 0) {
232         for (i = 0, nz = 0; i < n; i++)
233           if (al[i] != 0.0) nzr[nz++] = i;
234       } else {
235         for (i = 0, nz = 0; i < n; i++)
236           if (PetscAbsScalar(al[i]) > tol) nzr[nz++] = i;
237       }
238     }
239     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nz, nzr, PETSC_OWN_POINTER, nonzero));
240   } else *nonzero = NULL;
241   if (!cols) { /* nonzero rows */
242     PetscCall(VecRestoreArrayRead(l, &al));
243   } else {
244     PetscCall(VecRestoreArrayRead(r, &al));
245   }
246   PetscCall(VecDestroy(&l));
247   PetscCall(VecDestroy(&r));
248   PetscFunctionReturn(PETSC_SUCCESS);
249 }
250 
251 /*@
252       MatFindNonzeroRows - Locate all rows that are not completely zero in the matrix
253 
254   Input Parameter:
255 .    A  - the matrix
256 
257   Output Parameter:
258 .    keptrows - the rows that are not completely zero
259 
260   Level: intermediate
261 
262   Note:
263     `keptrows` is set to `NULL` if all rows are nonzero.
264 
265 .seealso: [](chapter_matrices), `Mat`, `MatFindZeroRows()`
266  @*/
267 PetscErrorCode MatFindNonzeroRows(Mat mat, IS *keptrows)
268 {
269   PetscFunctionBegin;
270   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
271   PetscValidType(mat, 1);
272   PetscValidPointer(keptrows, 2);
273   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
274   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
275   if (mat->ops->findnonzerorows) PetscUseTypeMethod(mat, findnonzerorows, keptrows);
276   else PetscCall(MatFindNonzeroRowsOrCols_Basic(mat, PETSC_FALSE, 0.0, keptrows));
277   PetscFunctionReturn(PETSC_SUCCESS);
278 }
279 
280 /*@
281       MatFindZeroRows - Locate all rows that are completely zero in the matrix
282 
283   Input Parameter:
284 .    A  - the matrix
285 
286   Output Parameter:
287 .    zerorows - the rows that are completely zero
288 
289   Level: intermediate
290 
291   Note:
292     `zerorows` is set to `NULL` if no rows are zero.
293 
294 .seealso: [](chapter_matrices), `Mat`, `MatFindNonzeroRows()`
295  @*/
296 PetscErrorCode MatFindZeroRows(Mat mat, IS *zerorows)
297 {
298   IS       keptrows;
299   PetscInt m, n;
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
303   PetscValidType(mat, 1);
304   PetscValidPointer(zerorows, 2);
305   PetscCall(MatFindNonzeroRows(mat, &keptrows));
306   /* MatFindNonzeroRows sets keptrows to NULL if there are no zero rows.
307      In keeping with this convention, we set zerorows to NULL if there are no zero
308      rows. */
309   if (keptrows == NULL) {
310     *zerorows = NULL;
311   } else {
312     PetscCall(MatGetOwnershipRange(mat, &m, &n));
313     PetscCall(ISComplement(keptrows, m, n, zerorows));
314     PetscCall(ISDestroy(&keptrows));
315   }
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@
320    MatGetDiagonalBlock - Returns the part of the matrix associated with the on-process coupling
321 
322    Not Collective
323 
324    Input Parameter:
325 .   A - the matrix
326 
327    Output Parameter:
328 .   a - the diagonal part (which is a SEQUENTIAL matrix)
329 
330    Level: advanced
331 
332    Notes:
333    See `MatCreateAIJ()` for more information on the "diagonal part" of the matrix.
334 
335    Use caution, as the reference count on the returned matrix is not incremented and it is used as part of `A`'s normal operation.
336 
337 .seealso: [](chapter_matrices), `Mat`, `MatCreateAIJ()`, `MATAIJ`, `MATBAIJ`, `MATSBAIJ`
338 @*/
339 PetscErrorCode MatGetDiagonalBlock(Mat A, Mat *a)
340 {
341   PetscFunctionBegin;
342   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
343   PetscValidType(A, 1);
344   PetscValidPointer(a, 2);
345   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
346   if (A->ops->getdiagonalblock) PetscUseTypeMethod(A, getdiagonalblock, a);
347   else {
348     PetscMPIInt size;
349 
350     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
351     PetscCheck(size == 1, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Not for parallel matrix type %s", ((PetscObject)A)->type_name);
352     *a = A;
353   }
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 /*@
358    MatGetTrace - Gets the trace of a matrix. The sum of the diagonal entries.
359 
360    Collective
361 
362    Input Parameter:
363 .  mat - the matrix
364 
365    Output Parameter:
366 .   trace - the sum of the diagonal entries
367 
368    Level: advanced
369 
370 .seealso: [](chapter_matrices), `Mat`
371 @*/
372 PetscErrorCode MatGetTrace(Mat mat, PetscScalar *trace)
373 {
374   Vec diag;
375 
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
378   PetscValidScalarPointer(trace, 2);
379   PetscCall(MatCreateVecs(mat, &diag, NULL));
380   PetscCall(MatGetDiagonal(mat, diag));
381   PetscCall(VecSum(diag, trace));
382   PetscCall(VecDestroy(&diag));
383   PetscFunctionReturn(PETSC_SUCCESS);
384 }
385 
386 /*@
387    MatRealPart - Zeros out the imaginary part of the matrix
388 
389    Logically Collective
390 
391    Input Parameter:
392 .  mat - the matrix
393 
394    Level: advanced
395 
396 .seealso: [](chapter_matrices), `Mat`, `MatImaginaryPart()`
397 @*/
398 PetscErrorCode MatRealPart(Mat mat)
399 {
400   PetscFunctionBegin;
401   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
402   PetscValidType(mat, 1);
403   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
404   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
405   MatCheckPreallocated(mat, 1);
406   PetscUseTypeMethod(mat, realpart);
407   PetscFunctionReturn(PETSC_SUCCESS);
408 }
409 
410 /*@C
411    MatGetGhosts - Get the global indices of all ghost nodes defined by the sparse matrix
412 
413    Collective
414 
415    Input Parameter:
416 .  mat - the matrix
417 
418    Output Parameters:
419 +   nghosts - number of ghosts (for `MATBAIJ` and `MATSBAIJ` matrices there is one ghost for each block)
420 -   ghosts - the global indices of the ghost points
421 
422    Level: advanced
423 
424    Note:
425    `nghosts` and `ghosts` are suitable to pass into `VecCreateGhost()`
426 
427 .seealso: [](chapter_matrices), `Mat`, `VecCreateGhost()`
428 @*/
429 PetscErrorCode MatGetGhosts(Mat mat, PetscInt *nghosts, const PetscInt *ghosts[])
430 {
431   PetscFunctionBegin;
432   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
433   PetscValidType(mat, 1);
434   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
435   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
436   if (mat->ops->getghosts) PetscUseTypeMethod(mat, getghosts, nghosts, ghosts);
437   else {
438     if (nghosts) *nghosts = 0;
439     if (ghosts) *ghosts = NULL;
440   }
441   PetscFunctionReturn(PETSC_SUCCESS);
442 }
443 
444 /*@
445    MatImaginaryPart - Moves the imaginary part of the matrix to the real part and zeros the imaginary part
446 
447    Logically Collective
448 
449    Input Parameter:
450 .  mat - the matrix
451 
452    Level: advanced
453 
454 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`
455 @*/
456 PetscErrorCode MatImaginaryPart(Mat mat)
457 {
458   PetscFunctionBegin;
459   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
460   PetscValidType(mat, 1);
461   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
462   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
463   MatCheckPreallocated(mat, 1);
464   PetscUseTypeMethod(mat, imaginarypart);
465   PetscFunctionReturn(PETSC_SUCCESS);
466 }
467 
468 /*@
469    MatMissingDiagonal - Determine if sparse matrix is missing a diagonal entry (or block entry for `MATBAIJ` and `MATSBAIJ` matrices)
470 
471    Not Collective
472 
473    Input Parameter:
474 .  mat - the matrix
475 
476    Output Parameters:
477 +  missing - is any diagonal missing
478 -  dd - first diagonal entry that is missing (optional) on this process
479 
480    Level: advanced
481 
482 .seealso: [](chapter_matrices), `Mat`
483 @*/
484 PetscErrorCode MatMissingDiagonal(Mat mat, PetscBool *missing, PetscInt *dd)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
488   PetscValidType(mat, 1);
489   PetscValidBoolPointer(missing, 2);
490   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix %s", ((PetscObject)mat)->type_name);
491   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
492   PetscUseTypeMethod(mat, missingdiagonal, missing, dd);
493   PetscFunctionReturn(PETSC_SUCCESS);
494 }
495 
496 /*@C
497    MatGetRow - Gets a row of a matrix.  You MUST call `MatRestoreRow()`
498    for each row that you get to ensure that your application does
499    not bleed memory.
500 
501    Not Collective
502 
503    Input Parameters:
504 +  mat - the matrix
505 -  row - the row to get
506 
507    Output Parameters:
508 +  ncols -  if not `NULL`, the number of nonzeros in the row
509 .  cols - if not `NULL`, the column numbers
510 -  vals - if not `NULL`, the values
511 
512    Level: advanced
513 
514    Notes:
515    This routine is provided for people who need to have direct access
516    to the structure of a matrix.  We hope that we provide enough
517    high-level matrix routines that few users will need it.
518 
519    `MatGetRow()` always returns 0-based column indices, regardless of
520    whether the internal representation is 0-based (default) or 1-based.
521 
522    For better efficiency, set cols and/or vals to `NULL` if you do
523    not wish to extract these quantities.
524 
525    The user can only examine the values extracted with `MatGetRow()`;
526    the values cannot be altered.  To change the matrix entries, one
527    must use `MatSetValues()`.
528 
529    You can only have one call to `MatGetRow()` outstanding for a particular
530    matrix at a time, per processor. `MatGetRow()` can only obtain rows
531    associated with the given processor, it cannot get rows from the
532    other processors; for that we suggest using `MatCreateSubMatrices()`, then
533    MatGetRow() on the submatrix. The row index passed to `MatGetRow()`
534    is in the global number of rows.
535 
536    Use `MatGetRowIJ()` and `MatRestoreRowIJ()` to access all the local indices of the sparse matrix.
537 
538    Use `MatSeqAIJGetArray()` and similar functions to access the numerical values for certain matrix types directly.
539 
540    Fortran Note:
541    The calling sequence is
542 .vb
543    MatGetRow(matrix,row,ncols,cols,values,ierr)
544          Mat     matrix (input)
545          integer row    (input)
546          integer ncols  (output)
547          integer cols(maxcols) (output)
548          double precision (or double complex) values(maxcols) output
549 .ve
550    where maxcols >= maximum nonzeros in any row of the matrix.
551 
552    Caution:
553    Do not try to change the contents of the output arrays (`cols` and `vals`).
554    In some cases, this may corrupt the matrix.
555 
556 .seealso: [](chapter_matrices), `Mat`, `MatRestoreRow()`, `MatSetValues()`, `MatGetValues()`, `MatCreateSubMatrices()`, `MatGetDiagonal()`, `MatGetRowIJ()`, `MatRestoreRowIJ()`
557 @*/
558 PetscErrorCode MatGetRow(Mat mat, PetscInt row, PetscInt *ncols, const PetscInt *cols[], const PetscScalar *vals[])
559 {
560   PetscInt incols;
561 
562   PetscFunctionBegin;
563   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
564   PetscValidType(mat, 1);
565   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
566   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
567   MatCheckPreallocated(mat, 1);
568   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);
569   PetscCall(PetscLogEventBegin(MAT_GetRow, mat, 0, 0, 0));
570   PetscUseTypeMethod(mat, getrow, row, &incols, (PetscInt **)cols, (PetscScalar **)vals);
571   if (ncols) *ncols = incols;
572   PetscCall(PetscLogEventEnd(MAT_GetRow, mat, 0, 0, 0));
573   PetscFunctionReturn(PETSC_SUCCESS);
574 }
575 
576 /*@
577    MatConjugate - replaces the matrix values with their complex conjugates
578 
579    Logically Collective
580 
581    Input Parameter:
582 .  mat - the matrix
583 
584    Level: advanced
585 
586 .seealso: [](chapter_matrices), `Mat`, `MatRealPart()`, `MatImaginaryPart()`, `VecConjugate()`, `MatTranspose()`
587 @*/
588 PetscErrorCode MatConjugate(Mat mat)
589 {
590   PetscFunctionBegin;
591   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
592   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
593   if (PetscDefined(USE_COMPLEX) && mat->hermitian != PETSC_BOOL3_TRUE) {
594     PetscUseTypeMethod(mat, conjugate);
595     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
596   }
597   PetscFunctionReturn(PETSC_SUCCESS);
598 }
599 
600 /*@C
601    MatRestoreRow - Frees any temporary space allocated by `MatGetRow()`.
602 
603    Not Collective
604 
605    Input Parameters:
606 +  mat - the matrix
607 .  row - the row to get
608 .  ncols - the number of nonzeros
609 .  cols - the columns of the nonzeros
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: [](chapter_matrices), `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   PetscUseTypeMethod(mat, restorerow, 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 Parameter:
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: [](chapter_matrices), `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 Parameter:
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: [](chapter_matrices), `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: [](chapter_matrices), `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: [](chapter_matrices), `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: [](chapter_matrices), `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   size_t len1, len2, new_len;
801 
802   PetscFunctionBegin;
803   PetscValidHeader(A, 1);
804   if (!prefix) PetscFunctionReturn(PETSC_SUCCESS);
805   if (!A->factorprefix) {
806     PetscCall(MatSetOptionsPrefixFactor(A, prefix));
807     PetscFunctionReturn(PETSC_SUCCESS);
808   }
809   PetscCheck(prefix[0] != '-', PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
810 
811   PetscCall(PetscStrlen(A->factorprefix, &len1));
812   PetscCall(PetscStrlen(prefix, &len2));
813   new_len = len1 + len2 + 1;
814   PetscCall(PetscRealloc(new_len * sizeof(*(A->factorprefix)), &A->factorprefix));
815   PetscCall(PetscStrncpy(A->factorprefix + len1, prefix, len2 + 1));
816   PetscFunctionReturn(PETSC_SUCCESS);
817 }
818 
819 /*@C
820    MatAppendOptionsPrefix - Appends to the prefix used for searching for all
821    matrix options in the database.
822 
823    Logically Collective
824 
825    Input Parameters:
826 +  A - the matrix
827 -  prefix - the prefix to prepend to all option names
828 
829    Level: advanced
830 
831    Note:
832    A hyphen (-) must NOT be given at the beginning of the prefix name.
833    The first character of all runtime options is AUTOMATICALLY the hyphen.
834 
835 .seealso: [](chapter_matrices), `Mat`, `MatGetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefix()`
836 @*/
837 PetscErrorCode MatAppendOptionsPrefix(Mat A, const char prefix[])
838 {
839   PetscFunctionBegin;
840   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
841   PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)A, prefix));
842   PetscFunctionReturn(PETSC_SUCCESS);
843 }
844 
845 /*@C
846    MatGetOptionsPrefix - Gets the prefix used for searching for all
847    matrix options in the database.
848 
849    Not Collective
850 
851    Input Parameter:
852 .  A - the matrix
853 
854    Output Parameter:
855 .  prefix - pointer to the prefix string used
856 
857    Level: advanced
858 
859    Fortran Note:
860    The user should pass in a string `prefix` of
861    sufficient length to hold the prefix.
862 
863 .seealso: [](chapter_matrices), `Mat`, `MatAppendOptionsPrefix()`, `MatSetOptionsPrefix()`, `MatAppendOptionsPrefixFactor()`, `MatSetOptionsPrefixFactor()`
864 @*/
865 PetscErrorCode MatGetOptionsPrefix(Mat A, const char *prefix[])
866 {
867   PetscFunctionBegin;
868   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
869   PetscValidPointer(prefix, 2);
870   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)A, prefix));
871   PetscFunctionReturn(PETSC_SUCCESS);
872 }
873 
874 /*@
875    MatResetPreallocation - Reset matrix to use the original nonzero pattern provided by users.
876 
877    Collective
878 
879    Input Parameter:
880 .  A - the matrix
881 
882    Level: beginner
883 
884    Notes:
885    The allocated memory will be shrunk after calling `MatAssemblyBegin()` and `MatAssemblyEnd()` with `MAT_FINAL_ASSEMBLY`.
886 
887    Users can reset the preallocation to access the original memory.
888 
889    Currently only supported for  `MATAIJ` matrices.
890 
891 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJSetPreallocation()`, `MatMPIAIJSetPreallocation()`, `MatXAIJSetPreallocation()`
892 @*/
893 PetscErrorCode MatResetPreallocation(Mat A)
894 {
895   PetscFunctionBegin;
896   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
897   PetscValidType(A, 1);
898   PetscUseMethod(A, "MatResetPreallocation_C", (Mat), (A));
899   PetscFunctionReturn(PETSC_SUCCESS);
900 }
901 
902 /*@
903    MatSetUp - Sets up the internal matrix data structures for later use.
904 
905    Collective
906 
907    Input Parameter:
908 .  A - the matrix
909 
910    Level: intermediate
911 
912    Notes:
913    If the user has not set preallocation for this matrix then an efficient algorithm will be used for the first round of
914    setting values in the matrix.
915 
916    If a suitable preallocation routine is used, this function does not need to be called.
917 
918    This routine is called internally by other matrix functions when needed so rarely needs to be called by users
919 
920 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatCreate()`, `MatDestroy()`, `MatXAIJSetPreallocation()`
921 @*/
922 PetscErrorCode MatSetUp(Mat A)
923 {
924   PetscFunctionBegin;
925   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
926   if (!((PetscObject)A)->type_name) {
927     PetscMPIInt size;
928 
929     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A), &size));
930     PetscCall(MatSetType(A, size == 1 ? MATSEQAIJ : MATMPIAIJ));
931   }
932   if (!A->preallocated) PetscTryTypeMethod(A, setup);
933   PetscCall(PetscLayoutSetUp(A->rmap));
934   PetscCall(PetscLayoutSetUp(A->cmap));
935   A->preallocated = PETSC_TRUE;
936   PetscFunctionReturn(PETSC_SUCCESS);
937 }
938 
939 #if defined(PETSC_HAVE_SAWS)
940   #include <petscviewersaws.h>
941 #endif
942 
943 /*@C
944    MatViewFromOptions - View properties of the matrix based on options set in the options database
945 
946    Collective
947 
948    Input Parameters:
949 +  A - the matrix
950 .  obj - optional additional object that provides the options prefix to use
951 -  name - command line option
952 
953   Options Database Key:
954 .  -mat_view [viewertype]:... - the viewer and its options
955 
956    Level: intermediate
957 
958   Notes:
959 .vb
960     If no value is provided ascii:stdout is used
961        ascii[:[filename][:[format][:append]]]    defaults to stdout - format can be one of ascii_info, ascii_info_detail, or ascii_matlab,
962                                                   for example ascii::ascii_info prints just the information about the object not all details
963                                                   unless :append is given filename opens in write mode, overwriting what was already there
964        binary[:[filename][:[format][:append]]]   defaults to the file binaryoutput
965        draw[:drawtype[:filename]]                for example, draw:tikz, draw:tikz:figure.tex  or draw:x
966        socket[:port]                             defaults to the standard output port
967        saws[:communicatorname]                    publishes object to the Scientific Application Webserver (SAWs)
968 .ve
969 
970 .seealso: [](chapter_matrices), `Mat`, `MatView()`, `PetscObjectViewFromOptions()`, `MatCreate()`
971 @*/
972 PetscErrorCode MatViewFromOptions(Mat A, PetscObject obj, const char name[])
973 {
974   PetscFunctionBegin;
975   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
976   PetscCall(PetscObjectViewFromOptions((PetscObject)A, obj, name));
977   PetscFunctionReturn(PETSC_SUCCESS);
978 }
979 
980 /*@C
981    MatView - display information about a matrix in a variety ways
982 
983    Collective
984 
985    Input Parameters:
986 +  mat - the matrix
987 -  viewer - visualization context
988 
989    Options Database Keys:
990 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatAssemblyEnd()`
991 .  -mat_view ::ascii_info_detail - Prints more detailed info
992 .  -mat_view - Prints matrix in ASCII format
993 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
994 .  -mat_view draw - PetscDraws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
995 .  -display <name> - Sets display name (default is host)
996 .  -draw_pause <sec> - Sets number of seconds to pause after display
997 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (see Users-Manual: ch_matlab for details)
998 .  -viewer_socket_machine <machine> -
999 .  -viewer_socket_port <port> -
1000 .  -mat_view binary - save matrix to file in binary format
1001 -  -viewer_binary_filename <name> -
1002 
1003    Level: beginner
1004 
1005   Notes:
1006   The available visualization contexts include
1007 +    `PETSC_VIEWER_STDOUT_SELF` - for sequential matrices
1008 .    `PETSC_VIEWER_STDOUT_WORLD` - for parallel matrices created on `PETSC_COMM_WORLD`
1009 .    `PETSC_VIEWER_STDOUT_`(comm) - for matrices created on MPI communicator comm
1010 -     `PETSC_VIEWER_DRAW_WORLD` - graphical display of nonzero structure
1011 
1012    The user can open alternative visualization contexts with
1013 +    `PetscViewerASCIIOpen()` - Outputs matrix to a specified file
1014 .    `PetscViewerBinaryOpen()` - Outputs matrix in binary to a
1015          specified file; corresponding input uses MatLoad()
1016 .    `PetscViewerDrawOpen()` - Outputs nonzero matrix structure to
1017          an X window display
1018 -    `PetscViewerSocketOpen()` - Outputs matrix to Socket viewer.
1019          Currently only the sequential dense and AIJ
1020          matrix types support the Socket viewer.
1021 
1022    The user can call `PetscViewerPushFormat()` to specify the output
1023    format of ASCII printed objects (when using `PETSC_VIEWER_STDOUT_SELF`,
1024    `PETSC_VIEWER_STDOUT_WORLD` and `PetscViewerASCIIOpen()`).  Available formats include
1025 +    `PETSC_VIEWER_DEFAULT` - default, prints matrix contents
1026 .    `PETSC_VIEWER_ASCII_MATLAB` - prints matrix contents in Matlab format
1027 .    `PETSC_VIEWER_ASCII_DENSE` - prints entire matrix including zeros
1028 .    `PETSC_VIEWER_ASCII_COMMON` - prints matrix contents, using a sparse
1029          format common among all matrix types
1030 .    `PETSC_VIEWER_ASCII_IMPL` - prints matrix contents, using an implementation-specific
1031          format (which is in many cases the same as the default)
1032 .    `PETSC_VIEWER_ASCII_INFO` - prints basic information about the matrix
1033          size and structure (not the matrix entries)
1034 -    `PETSC_VIEWER_ASCII_INFO_DETAIL` - prints more detailed information about
1035          the matrix structure
1036 
1037     The ASCII viewers are only recommended for small matrices on at most a moderate number of processes,
1038     the program will seemingly hang and take hours for larger matrices, for larger matrices one should use the binary format.
1039 
1040     In the debugger you can do "call MatView(mat,0)" to display the matrix. (The same holds for any PETSc object viewer).
1041 
1042     See the manual page for `MatLoad()` for the exact format of the binary file when the binary
1043       viewer is used.
1044 
1045       See share/petsc/matlab/PetscBinaryRead.m for a Matlab code that can read in the binary file when the binary
1046       viewer is used and lib/petsc/bin/PetscBinaryIO.py for loading them into Python.
1047 
1048       One can use '-mat_view draw -draw_pause -1' to pause the graphical display of matrix nonzero structure,
1049       and then use the following mouse functions.
1050 .vb
1051   left mouse: zoom in
1052   middle mouse: zoom out
1053   right mouse: continue with the simulation
1054 .ve
1055 
1056 .seealso: [](chapter_matrices), `Mat`, `PetscViewerPushFormat()`, `PetscViewerASCIIOpen()`, `PetscViewerDrawOpen()`, `PetscViewer`,
1057           `PetscViewerSocketOpen()`, `PetscViewerBinaryOpen()`, `MatLoad()`, `MatViewFromOptions()`
1058 @*/
1059 PetscErrorCode MatView(Mat mat, PetscViewer viewer)
1060 {
1061   PetscInt          rows, cols, rbs, cbs;
1062   PetscBool         isascii, isstring, issaws;
1063   PetscViewerFormat format;
1064   PetscMPIInt       size;
1065 
1066   PetscFunctionBegin;
1067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1068   PetscValidType(mat, 1);
1069   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)mat), &viewer));
1070   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1071   PetscCheckSameComm(mat, 1, viewer, 2);
1072 
1073   PetscCall(PetscViewerGetFormat(viewer, &format));
1074   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
1075   if (size == 1 && format == PETSC_VIEWER_LOAD_BALANCE) PetscFunctionReturn(PETSC_SUCCESS);
1076 
1077   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSTRING, &isstring));
1078   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1079   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERSAWS, &issaws));
1080   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");
1081 
1082   PetscCall(PetscLogEventBegin(MAT_View, mat, viewer, 0, 0));
1083   if (isascii) {
1084     if (!mat->preallocated) {
1085       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been preallocated yet\n"));
1086       PetscFunctionReturn(PETSC_SUCCESS);
1087     }
1088     if (!mat->assembled) {
1089       PetscCall(PetscViewerASCIIPrintf(viewer, "Matrix has not been assembled yet\n"));
1090       PetscFunctionReturn(PETSC_SUCCESS);
1091     }
1092     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)mat, viewer));
1093     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) {
1094       MatNullSpace nullsp, transnullsp;
1095 
1096       PetscCall(PetscViewerASCIIPushTab(viewer));
1097       PetscCall(MatGetSize(mat, &rows, &cols));
1098       PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1099       if (rbs != 1 || cbs != 1) {
1100         if (rbs != cbs) PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", rbs=%" PetscInt_FMT ", cbs=%" PetscInt_FMT "\n", rows, cols, rbs, cbs));
1101         else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT ", bs=%" PetscInt_FMT "\n", rows, cols, rbs));
1102       } else PetscCall(PetscViewerASCIIPrintf(viewer, "rows=%" PetscInt_FMT ", cols=%" PetscInt_FMT "\n", rows, cols));
1103       if (mat->factortype) {
1104         MatSolverType solver;
1105         PetscCall(MatFactorGetSolverType(mat, &solver));
1106         PetscCall(PetscViewerASCIIPrintf(viewer, "package used to perform factorization: %s\n", solver));
1107       }
1108       if (mat->ops->getinfo) {
1109         MatInfo info;
1110         PetscCall(MatGetInfo(mat, MAT_GLOBAL_SUM, &info));
1111         PetscCall(PetscViewerASCIIPrintf(viewer, "total: nonzeros=%.f, allocated nonzeros=%.f\n", info.nz_used, info.nz_allocated));
1112         if (!mat->factortype) PetscCall(PetscViewerASCIIPrintf(viewer, "total number of mallocs used during MatSetValues calls=%" PetscInt_FMT "\n", (PetscInt)info.mallocs));
1113       }
1114       PetscCall(MatGetNullSpace(mat, &nullsp));
1115       PetscCall(MatGetTransposeNullSpace(mat, &transnullsp));
1116       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached null space\n"));
1117       if (transnullsp && transnullsp != nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached transposed null space\n"));
1118       PetscCall(MatGetNearNullSpace(mat, &nullsp));
1119       if (nullsp) PetscCall(PetscViewerASCIIPrintf(viewer, "  has attached near null space\n"));
1120       PetscCall(PetscViewerASCIIPushTab(viewer));
1121       PetscCall(MatProductView(mat, viewer));
1122       PetscCall(PetscViewerASCIIPopTab(viewer));
1123     }
1124   } else if (issaws) {
1125 #if defined(PETSC_HAVE_SAWS)
1126     PetscMPIInt rank;
1127 
1128     PetscCall(PetscObjectName((PetscObject)mat));
1129     PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
1130     if (!((PetscObject)mat)->amsmem && rank == 0) PetscCall(PetscObjectViewSAWs((PetscObject)mat, viewer));
1131 #endif
1132   } else if (isstring) {
1133     const char *type;
1134     PetscCall(MatGetType(mat, &type));
1135     PetscCall(PetscViewerStringSPrintf(viewer, " MatType: %-7.7s", type));
1136     PetscTryTypeMethod(mat, view, viewer);
1137   }
1138   if ((format == PETSC_VIEWER_NATIVE || format == PETSC_VIEWER_LOAD_BALANCE) && mat->ops->viewnative) {
1139     PetscCall(PetscViewerASCIIPushTab(viewer));
1140     PetscUseTypeMethod(mat, viewnative, viewer);
1141     PetscCall(PetscViewerASCIIPopTab(viewer));
1142   } else if (mat->ops->view) {
1143     PetscCall(PetscViewerASCIIPushTab(viewer));
1144     PetscUseTypeMethod(mat, view, viewer);
1145     PetscCall(PetscViewerASCIIPopTab(viewer));
1146   }
1147   if (isascii) {
1148     PetscCall(PetscViewerGetFormat(viewer, &format));
1149     if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_DETAIL) PetscCall(PetscViewerASCIIPopTab(viewer));
1150   }
1151   PetscCall(PetscLogEventEnd(MAT_View, mat, viewer, 0, 0));
1152   PetscFunctionReturn(PETSC_SUCCESS);
1153 }
1154 
1155 #if defined(PETSC_USE_DEBUG)
1156   #include <../src/sys/totalview/tv_data_display.h>
1157 PETSC_UNUSED static int TV_display_type(const struct _p_Mat *mat)
1158 {
1159   TV_add_row("Local rows", "int", &mat->rmap->n);
1160   TV_add_row("Local columns", "int", &mat->cmap->n);
1161   TV_add_row("Global rows", "int", &mat->rmap->N);
1162   TV_add_row("Global columns", "int", &mat->cmap->N);
1163   TV_add_row("Typename", TV_ascii_string_type, ((PetscObject)mat)->type_name);
1164   return TV_format_OK;
1165 }
1166 #endif
1167 
1168 /*@C
1169    MatLoad - Loads a matrix that has been stored in binary/HDF5 format
1170    with `MatView()`.  The matrix format is determined from the options database.
1171    Generates a parallel MPI matrix if the communicator has more than one
1172    processor.  The default matrix type is `MATAIJ`.
1173 
1174    Collective
1175 
1176    Input Parameters:
1177 +  mat - the newly loaded matrix, this needs to have been created with `MatCreate()`
1178             or some related function before a call to `MatLoad()`
1179 -  viewer - `PETSCVIEWERBINARY`/`PETSCVIEWERHDF5` file viewer
1180 
1181    Options Database Keys:
1182    Used with block matrix formats (`MATSEQBAIJ`,  ...) to specify
1183    block size
1184 .    -matload_block_size <bs> - set block size
1185 
1186    Level: beginner
1187 
1188    Notes:
1189    If the `Mat` type has not yet been given then `MATAIJ` is used, call `MatSetFromOptions()` on the
1190    `Mat` before calling this routine if you wish to set it from the options database.
1191 
1192    `MatLoad()` automatically loads into the options database any options
1193    given in the file filename.info where filename is the name of the file
1194    that was passed to the `PetscViewerBinaryOpen()`. The options in the info
1195    file will be ignored if you use the -viewer_binary_skip_info option.
1196 
1197    If the type or size of mat is not set before a call to `MatLoad()`, PETSc
1198    sets the default matrix type AIJ and sets the local and global sizes.
1199    If type and/or size is already set, then the same are used.
1200 
1201    In parallel, each processor can load a subset of rows (or the
1202    entire matrix).  This routine is especially useful when a large
1203    matrix is stored on disk and only part of it is desired on each
1204    processor.  For example, a parallel solver may access only some of
1205    the rows from each processor.  The algorithm used here reads
1206    relatively small blocks of data rather than reading the entire
1207    matrix and then subsetting it.
1208 
1209    Viewer's `PetscViewerType` must be either `PETSCVIEWERBINARY` or `PETSCVIEWERHDF5`.
1210    Such viewer can be created using `PetscViewerBinaryOpen()` or `PetscViewerHDF5Open()`,
1211    or the sequence like
1212 .vb
1213     `PetscViewer` v;
1214     `PetscViewerCreate`(`PETSC_COMM_WORLD`,&v);
1215     `PetscViewerSetType`(v,`PETSCVIEWERBINARY`);
1216     `PetscViewerSetFromOptions`(v);
1217     `PetscViewerFileSetMode`(v,`FILE_MODE_READ`);
1218     `PetscViewerFileSetName`(v,"datafile");
1219 .ve
1220    The optional `PetscViewerSetFromOptions()` call allows overriding `PetscViewerSetType()` using the option
1221 $ -viewer_type {binary, hdf5}
1222 
1223    See the example src/ksp/ksp/tutorials/ex27.c with the first approach,
1224    and src/mat/tutorials/ex10.c with the second approach.
1225 
1226    In case of `PETSCVIEWERBINARY`, a native PETSc binary format is used. Each of the blocks
1227    is read onto rank 0 and then shipped to its destination rank, one after another.
1228    Multiple objects, both matrices and vectors, can be stored within the same file.
1229    Their PetscObject name is ignored; they are loaded in the order of their storage.
1230 
1231    Most users should not need to know the details of the binary storage
1232    format, since `MatLoad()` and `MatView()` completely hide these details.
1233    But for anyone who's interested, the standard binary matrix storage
1234    format is
1235 
1236 .vb
1237     PetscInt    MAT_FILE_CLASSID
1238     PetscInt    number of rows
1239     PetscInt    number of columns
1240     PetscInt    total number of nonzeros
1241     PetscInt    *number nonzeros in each row
1242     PetscInt    *column indices of all nonzeros (starting index is zero)
1243     PetscScalar *values of all nonzeros
1244 .ve
1245 
1246    PETSc automatically does the byte swapping for
1247 machines that store the bytes reversed. Thus if you write your own binary
1248 read/write routines you have to swap the bytes; see `PetscBinaryRead()`
1249 and `PetscBinaryWrite()` to see how this may be done.
1250 
1251    In case of `PETSCVIEWERHDF5`, a parallel HDF5 reader is used.
1252    Each processor's chunk is loaded independently by its owning rank.
1253    Multiple objects, both matrices and vectors, can be stored within the same file.
1254    They are looked up by their PetscObject name.
1255 
1256    As the MATLAB MAT-File Version 7.3 format is also a HDF5 flavor, we decided to use
1257    by default the same structure and naming of the AIJ arrays and column count
1258    within the HDF5 file. This means that a MAT file saved with -v7.3 flag, e.g.
1259 $    save example.mat A b -v7.3
1260    can be directly read by this routine (see Reference 1 for details).
1261 
1262    Depending on your MATLAB version, this format might be a default,
1263    otherwise you can set it as default in Preferences.
1264 
1265    Unless -nocompression flag is used to save the file in MATLAB,
1266    PETSc must be configured with ZLIB package.
1267 
1268    See also examples src/mat/tutorials/ex10.c and src/ksp/ksp/tutorials/ex27.c
1269 
1270    This reader currently supports only real `MATSEQAIJ`, `MATMPIAIJ`, `MATSEQDENSE` and `MATMPIDENSE` matrices for `PETSCVIEWERHDF5`
1271 
1272    Corresponding `MatView()` is not yet implemented.
1273 
1274    The loaded matrix is actually a transpose of the original one in MATLAB,
1275    unless you push `PETSC_VIEWER_HDF5_MAT` format (see examples above).
1276    With this format, matrix is automatically transposed by PETSc,
1277    unless the matrix is marked as SPD or symmetric
1278    (see `MatSetOption()`, `MAT_SPD`, `MAT_SYMMETRIC`).
1279 
1280    References:
1281 .  * - MATLAB(R) Documentation, manual page of save(), https://www.mathworks.com/help/matlab/ref/save.html#btox10b-1-version
1282 
1283 .seealso: [](chapter_matrices), `Mat`, `PetscViewerBinaryOpen()`, `PetscViewerSetType()`, `MatView()`, `VecLoad()`
1284  @*/
1285 PetscErrorCode MatLoad(Mat mat, PetscViewer viewer)
1286 {
1287   PetscBool flg;
1288 
1289   PetscFunctionBegin;
1290   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1291   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
1292 
1293   if (!((PetscObject)mat)->type_name) PetscCall(MatSetType(mat, MATAIJ));
1294 
1295   flg = PETSC_FALSE;
1296   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_symmetric", &flg, NULL));
1297   if (flg) {
1298     PetscCall(MatSetOption(mat, MAT_SYMMETRIC, PETSC_TRUE));
1299     PetscCall(MatSetOption(mat, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
1300   }
1301   flg = PETSC_FALSE;
1302   PetscCall(PetscOptionsGetBool(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matload_spd", &flg, NULL));
1303   if (flg) PetscCall(MatSetOption(mat, MAT_SPD, PETSC_TRUE));
1304 
1305   PetscCall(PetscLogEventBegin(MAT_Load, mat, viewer, 0, 0));
1306   PetscUseTypeMethod(mat, load, viewer);
1307   PetscCall(PetscLogEventEnd(MAT_Load, mat, viewer, 0, 0));
1308   PetscFunctionReturn(PETSC_SUCCESS);
1309 }
1310 
1311 static PetscErrorCode MatDestroy_Redundant(Mat_Redundant **redundant)
1312 {
1313   Mat_Redundant *redund = *redundant;
1314 
1315   PetscFunctionBegin;
1316   if (redund) {
1317     if (redund->matseq) { /* via MatCreateSubMatrices()  */
1318       PetscCall(ISDestroy(&redund->isrow));
1319       PetscCall(ISDestroy(&redund->iscol));
1320       PetscCall(MatDestroySubMatrices(1, &redund->matseq));
1321     } else {
1322       PetscCall(PetscFree2(redund->send_rank, redund->recv_rank));
1323       PetscCall(PetscFree(redund->sbuf_j));
1324       PetscCall(PetscFree(redund->sbuf_a));
1325       for (PetscInt i = 0; i < redund->nrecvs; i++) {
1326         PetscCall(PetscFree(redund->rbuf_j[i]));
1327         PetscCall(PetscFree(redund->rbuf_a[i]));
1328       }
1329       PetscCall(PetscFree4(redund->sbuf_nz, redund->rbuf_nz, redund->rbuf_j, redund->rbuf_a));
1330     }
1331 
1332     if (redund->subcomm) PetscCall(PetscCommDestroy(&redund->subcomm));
1333     PetscCall(PetscFree(redund));
1334   }
1335   PetscFunctionReturn(PETSC_SUCCESS);
1336 }
1337 
1338 /*@C
1339    MatDestroy - Frees space taken by a matrix.
1340 
1341    Collective
1342 
1343    Input Parameter:
1344 .  A - the matrix
1345 
1346    Level: beginner
1347 
1348    Developer Note:
1349    Some special arrays of matrices are not destroyed in this routine but instead by the routines called by
1350    `MatDestroySubMatrices()`. Thus one must be sure that any changes here must also be made in those routines.
1351    `MatHeaderMerge()` and `MatHeaderReplace()` also manipulate the data in the `Mat` object and likely need changes
1352    if changes are needed here.
1353 
1354 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`
1355 @*/
1356 PetscErrorCode MatDestroy(Mat *A)
1357 {
1358   PetscFunctionBegin;
1359   if (!*A) PetscFunctionReturn(PETSC_SUCCESS);
1360   PetscValidHeaderSpecific(*A, MAT_CLASSID, 1);
1361   if (--((PetscObject)(*A))->refct > 0) {
1362     *A = NULL;
1363     PetscFunctionReturn(PETSC_SUCCESS);
1364   }
1365 
1366   /* if memory was published with SAWs then destroy it */
1367   PetscCall(PetscObjectSAWsViewOff((PetscObject)*A));
1368   PetscTryTypeMethod((*A), destroy);
1369 
1370   PetscCall(PetscFree((*A)->factorprefix));
1371   PetscCall(PetscFree((*A)->defaultvectype));
1372   PetscCall(PetscFree((*A)->defaultrandtype));
1373   PetscCall(PetscFree((*A)->bsizes));
1374   PetscCall(PetscFree((*A)->solvertype));
1375   for (PetscInt i = 0; i < MAT_FACTOR_NUM_TYPES; i++) PetscCall(PetscFree((*A)->preferredordering[i]));
1376   if ((*A)->redundant && (*A)->redundant->matseq[0] == *A) (*A)->redundant->matseq[0] = NULL;
1377   PetscCall(MatDestroy_Redundant(&(*A)->redundant));
1378   PetscCall(MatProductClear(*A));
1379   PetscCall(MatNullSpaceDestroy(&(*A)->nullsp));
1380   PetscCall(MatNullSpaceDestroy(&(*A)->transnullsp));
1381   PetscCall(MatNullSpaceDestroy(&(*A)->nearnullsp));
1382   PetscCall(MatDestroy(&(*A)->schur));
1383   PetscCall(PetscLayoutDestroy(&(*A)->rmap));
1384   PetscCall(PetscLayoutDestroy(&(*A)->cmap));
1385   PetscCall(PetscHeaderDestroy(A));
1386   PetscFunctionReturn(PETSC_SUCCESS);
1387 }
1388 
1389 /*@C
1390    MatSetValues - Inserts or adds a block of values into a matrix.
1391    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1392    MUST be called after all calls to `MatSetValues()` have been completed.
1393 
1394    Not Collective
1395 
1396    Input Parameters:
1397 +  mat - the matrix
1398 .  v - a logically two-dimensional array of values
1399 .  m - the number of rows
1400 .  idxm - the global indices of the rows
1401 .  n - the number of columns
1402 .  idxn - the global indices of the columns
1403 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1404 
1405    Level: beginner
1406 
1407    Notes:
1408    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1409 
1410    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1411    options cannot be mixed without intervening calls to the assembly
1412    routines.
1413 
1414    `MatSetValues()` uses 0-based row and column numbers in Fortran
1415    as well as in C.
1416 
1417    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1418    simply ignored. This allows easily inserting element stiffness matrices
1419    with homogeneous Dirchlet boundary conditions that you don't want represented
1420    in the matrix.
1421 
1422    Efficiency Alert:
1423    The routine `MatSetValuesBlocked()` may offer much better efficiency
1424    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1425 
1426    Developer Note:
1427    This is labeled with C so does not automatically generate Fortran stubs and interfaces
1428    because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1429 
1430 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1431           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`
1432 @*/
1433 PetscErrorCode MatSetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1434 {
1435   PetscFunctionBeginHot;
1436   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1437   PetscValidType(mat, 1);
1438   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1439   PetscValidIntPointer(idxm, 3);
1440   PetscValidIntPointer(idxn, 5);
1441   MatCheckPreallocated(mat, 1);
1442 
1443   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1444   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1445 
1446   if (PetscDefined(USE_DEBUG)) {
1447     PetscInt i, j;
1448 
1449     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1450     for (i = 0; i < m; i++) {
1451       for (j = 0; j < n; j++) {
1452         if (mat->erroriffailure && PetscIsInfOrNanScalar(v[i * n + j]))
1453 #if defined(PETSC_USE_COMPLEX)
1454           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]);
1455 #else
1456           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]);
1457 #endif
1458       }
1459     }
1460     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);
1461     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);
1462   }
1463 
1464   if (mat->assembled) {
1465     mat->was_assembled = PETSC_TRUE;
1466     mat->assembled     = PETSC_FALSE;
1467   }
1468   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1469   PetscUseTypeMethod(mat, setvalues, m, idxm, n, idxn, v, addv);
1470   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1471   PetscFunctionReturn(PETSC_SUCCESS);
1472 }
1473 
1474 /*@C
1475    MatSetValuesIS - Inserts or adds a block of values into a matrix using an `IS` to indicate the rows and columns
1476    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
1477    MUST be called after all calls to `MatSetValues()` have been completed.
1478 
1479    Not Collective
1480 
1481    Input Parameters:
1482 +  mat - the matrix
1483 .  v - a logically two-dimensional array of values
1484 .  ism - the rows to provide
1485 .  isn - the columns to provide
1486 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
1487 
1488    Level: beginner
1489 
1490    Notes:
1491    By default the values, `v`, are stored row-oriented. See `MatSetOption()` for other options.
1492 
1493    Calls to `MatSetValues()` with the `INSERT_VALUES` and `ADD_VALUES`
1494    options cannot be mixed without intervening calls to the assembly
1495    routines.
1496 
1497    `MatSetValues()` uses 0-based row and column numbers in Fortran
1498    as well as in C.
1499 
1500    Negative indices may be passed in `ism` and `isn`, these rows and columns are
1501    simply ignored. This allows easily inserting element stiffness matrices
1502    with homogeneous Dirchlet boundary conditions that you don't want represented
1503    in the matrix.
1504 
1505    Efficiency Alert:
1506    The routine `MatSetValuesBlocked()` may offer much better efficiency
1507    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1508 
1509     This is currently not optimized for any particular `ISType`
1510 
1511    Developer Notes:
1512     This is labeled with C so does not automatically generate Fortran stubs and interfaces
1513                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
1514 
1515 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatSetValues()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1516           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1517 @*/
1518 PetscErrorCode MatSetValuesIS(Mat mat, IS ism, IS isn, const PetscScalar v[], InsertMode addv)
1519 {
1520   PetscInt        m, n;
1521   const PetscInt *rows, *cols;
1522 
1523   PetscFunctionBeginHot;
1524   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1525   PetscCall(ISGetIndices(ism, &rows));
1526   PetscCall(ISGetIndices(isn, &cols));
1527   PetscCall(ISGetLocalSize(ism, &m));
1528   PetscCall(ISGetLocalSize(isn, &n));
1529   PetscCall(MatSetValues(mat, m, rows, n, cols, v, addv));
1530   PetscCall(ISRestoreIndices(ism, &rows));
1531   PetscCall(ISRestoreIndices(isn, &cols));
1532   PetscFunctionReturn(PETSC_SUCCESS);
1533 }
1534 
1535 /*@
1536    MatSetValuesRowLocal - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1537         values into a matrix
1538 
1539    Not Collective
1540 
1541    Input Parameters:
1542 +  mat - the matrix
1543 .  row - the (block) row to set
1544 -  v - a logically two-dimensional array of values
1545 
1546    Level: intermediate
1547 
1548    Notes:
1549    The values, `v`, are column-oriented (for the block version) and sorted
1550 
1551    All the nonzeros in the row must be provided
1552 
1553    The matrix must have previously had its column indices set, likely by having been assembled.
1554 
1555    The row must belong to this process
1556 
1557 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1558           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetValuesRow()`, `MatSetLocalToGlobalMapping()`
1559 @*/
1560 PetscErrorCode MatSetValuesRowLocal(Mat mat, PetscInt row, const PetscScalar v[])
1561 {
1562   PetscInt globalrow;
1563 
1564   PetscFunctionBegin;
1565   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1566   PetscValidType(mat, 1);
1567   PetscValidScalarPointer(v, 3);
1568   PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, 1, &row, &globalrow));
1569   PetscCall(MatSetValuesRow(mat, globalrow, v));
1570   PetscFunctionReturn(PETSC_SUCCESS);
1571 }
1572 
1573 /*@
1574    MatSetValuesRow - Inserts a row (block row for `MATBAIJ` matrices) of nonzero
1575         values into a matrix
1576 
1577    Not Collective
1578 
1579    Input Parameters:
1580 +  mat - the matrix
1581 .  row - the (block) row to set
1582 -  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
1583 
1584    Level: advanced
1585 
1586    Notes:
1587    The values, `v`, are column-oriented for the block version.
1588 
1589    All the nonzeros in the row must be provided
1590 
1591    THE MATRIX MUST HAVE PREVIOUSLY HAD ITS COLUMN INDICES SET. IT IS RARE THAT THIS ROUTINE IS USED, usually `MatSetValues()` is used.
1592 
1593    The row must belong to this process
1594 
1595 .seealso: [](chapter_matrices), `Mat`, `MatSetValues()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
1596           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`
1597 @*/
1598 PetscErrorCode MatSetValuesRow(Mat mat, PetscInt row, const PetscScalar v[])
1599 {
1600   PetscFunctionBeginHot;
1601   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1602   PetscValidType(mat, 1);
1603   MatCheckPreallocated(mat, 1);
1604   PetscValidScalarPointer(v, 3);
1605   PetscCheck(mat->insertmode != ADD_VALUES, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add and insert values");
1606   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1607   mat->insertmode = INSERT_VALUES;
1608 
1609   if (mat->assembled) {
1610     mat->was_assembled = PETSC_TRUE;
1611     mat->assembled     = PETSC_FALSE;
1612   }
1613   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1614   PetscUseTypeMethod(mat, setvaluesrow, row, v);
1615   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
1616   PetscFunctionReturn(PETSC_SUCCESS);
1617 }
1618 
1619 /*@
1620    MatSetValuesStencil - Inserts or adds a block of values into a matrix.
1621      Using structured grid indexing
1622 
1623    Not Collective
1624 
1625    Input Parameters:
1626 +  mat - the matrix
1627 .  m - number of rows being entered
1628 .  idxm - grid coordinates (and component number when dof > 1) for matrix rows being entered
1629 .  n - number of columns being entered
1630 .  idxn - grid coordinates (and component number when dof > 1) for matrix columns being entered
1631 .  v - a logically two-dimensional array of values
1632 -  addv - either `ADD_VALUES` to add to existing entries at that location or `INSERT_VALUES` to replace existing entries with new values
1633 
1634    Level: beginner
1635 
1636    Notes:
1637    By default the values, `v`, are row-oriented.  See `MatSetOption()` for other options.
1638 
1639    Calls to `MatSetValuesStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1640    options cannot be mixed without intervening calls to the assembly
1641    routines.
1642 
1643    The grid coordinates are across the entire grid, not just the local portion
1644 
1645    `MatSetValuesStencil()` uses 0-based row and column numbers in Fortran
1646    as well as in C.
1647 
1648    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1649 
1650    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1651    or call `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1652 
1653    The columns and rows in the stencil passed in MUST be contained within the
1654    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1655    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1656    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1657    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1658 
1659    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
1660    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
1661    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
1662    `DM_BOUNDARY_PERIODIC` boundary type.
1663 
1664    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
1665    a single value per point) you can skip filling those indices.
1666 
1667    Inspired by the structured grid interface to the HYPRE package
1668    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1669 
1670    Efficiency Alert:
1671    The routine `MatSetValuesBlockedStencil()` may offer much better efficiency
1672    for users of block sparse formats (`MATSEQBAIJ` and `MATMPIBAIJ`).
1673 
1674    Fortran Note:
1675    `idxm` and `idxn` should be declared as
1676 $     MatStencil idxm(4,m),idxn(4,n)
1677    and the values inserted using
1678 .vb
1679     idxm(MatStencil_i,1) = i
1680     idxm(MatStencil_j,1) = j
1681     idxm(MatStencil_k,1) = k
1682     idxm(MatStencil_c,1) = c
1683     etc
1684 .ve
1685 
1686 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1687           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`
1688 @*/
1689 PetscErrorCode MatSetValuesStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1690 {
1691   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1692   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1693   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1694 
1695   PetscFunctionBegin;
1696   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1697   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1698   PetscValidType(mat, 1);
1699   PetscValidPointer(idxm, 3);
1700   PetscValidPointer(idxn, 5);
1701 
1702   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1703     jdxm = buf;
1704     jdxn = buf + m;
1705   } else {
1706     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1707     jdxm = bufm;
1708     jdxn = bufn;
1709   }
1710   for (i = 0; i < m; i++) {
1711     for (j = 0; j < 3 - sdim; j++) dxm++;
1712     tmp = *dxm++ - starts[0];
1713     for (j = 0; j < dim - 1; j++) {
1714       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1715       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1716     }
1717     if (mat->stencil.noc) dxm++;
1718     jdxm[i] = tmp;
1719   }
1720   for (i = 0; i < n; i++) {
1721     for (j = 0; j < 3 - sdim; j++) dxn++;
1722     tmp = *dxn++ - starts[0];
1723     for (j = 0; j < dim - 1; j++) {
1724       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1725       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1726     }
1727     if (mat->stencil.noc) dxn++;
1728     jdxn[i] = tmp;
1729   }
1730   PetscCall(MatSetValuesLocal(mat, m, jdxm, n, jdxn, v, addv));
1731   PetscCall(PetscFree2(bufm, bufn));
1732   PetscFunctionReturn(PETSC_SUCCESS);
1733 }
1734 
1735 /*@
1736    MatSetValuesBlockedStencil - Inserts or adds a block of values into a matrix.
1737      Using structured grid indexing
1738 
1739    Not Collective
1740 
1741    Input Parameters:
1742 +  mat - the matrix
1743 .  m - number of rows being entered
1744 .  idxm - grid coordinates for matrix rows being entered
1745 .  n - number of columns being entered
1746 .  idxn - grid coordinates for matrix columns being entered
1747 .  v - a logically two-dimensional array of values
1748 -  addv - either `ADD_VALUES` to add to existing entries or `INSERT_VALUES` to replace existing entries with new values
1749 
1750    Level: beginner
1751 
1752    Notes:
1753    By default the values, `v`, are row-oriented and unsorted.
1754    See `MatSetOption()` for other options.
1755 
1756    Calls to `MatSetValuesBlockedStencil()` with the `INSERT_VALUES` and `ADD_VALUES`
1757    options cannot be mixed without intervening calls to the assembly
1758    routines.
1759 
1760    The grid coordinates are across the entire grid, not just the local portion
1761 
1762    `MatSetValuesBlockedStencil()` uses 0-based row and column numbers in Fortran
1763    as well as in C.
1764 
1765    For setting/accessing vector values via array coordinates you can use the `DMDAVecGetArray()` routine
1766 
1767    In order to use this routine you must either obtain the matrix with `DMCreateMatrix()`
1768    or call `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()` and `MatSetStencil()` first.
1769 
1770    The columns and rows in the stencil passed in MUST be contained within the
1771    ghost region of the given process as set with DMDACreateXXX() or `MatSetStencil()`. For example,
1772    if you create a `DMDA` with an overlap of one grid level and on a particular process its first
1773    local nonghost x logical coordinate is 6 (so its first ghost x logical coordinate is 5) the
1774    first i index you can use in your column and row indices in `MatSetStencil()` is 5.
1775 
1776    Negative indices may be passed in idxm and idxn, these rows and columns are
1777    simply ignored. This allows easily inserting element stiffness matrices
1778    with homogeneous Dirchlet boundary conditions that you don't want represented
1779    in the matrix.
1780 
1781    Inspired by the structured grid interface to the HYPRE package
1782    (https://computation.llnl.gov/projects/hypre-scalable-linear-solvers-multigrid-methods)
1783 
1784    Fortran Note:
1785    `idxm` and `idxn` should be declared as
1786 $     MatStencil idxm(4,m),idxn(4,n)
1787    and the values inserted using
1788 .vb
1789     idxm(MatStencil_i,1) = i
1790     idxm(MatStencil_j,1) = j
1791     idxm(MatStencil_k,1) = k
1792    etc
1793 .ve
1794 
1795 .seealso: [](chapter_matrices), `Mat`, `DMDA`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1796           `MatSetValues()`, `MatSetValuesStencil()`, `MatSetStencil()`, `DMCreateMatrix()`, `DMDAVecGetArray()`, `MatStencil`,
1797           `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`
1798 @*/
1799 PetscErrorCode MatSetValuesBlockedStencil(Mat mat, PetscInt m, const MatStencil idxm[], PetscInt n, const MatStencil idxn[], const PetscScalar v[], InsertMode addv)
1800 {
1801   PetscInt  buf[8192], *bufm = NULL, *bufn = NULL, *jdxm, *jdxn;
1802   PetscInt  j, i, dim = mat->stencil.dim, *dims = mat->stencil.dims + 1, tmp;
1803   PetscInt *starts = mat->stencil.starts, *dxm = (PetscInt *)idxm, *dxn = (PetscInt *)idxn, sdim = dim - (1 - (PetscInt)mat->stencil.noc);
1804 
1805   PetscFunctionBegin;
1806   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1807   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1808   PetscValidType(mat, 1);
1809   PetscValidPointer(idxm, 3);
1810   PetscValidPointer(idxn, 5);
1811   PetscValidScalarPointer(v, 6);
1812 
1813   if ((m + n) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1814     jdxm = buf;
1815     jdxn = buf + m;
1816   } else {
1817     PetscCall(PetscMalloc2(m, &bufm, n, &bufn));
1818     jdxm = bufm;
1819     jdxn = bufn;
1820   }
1821   for (i = 0; i < m; i++) {
1822     for (j = 0; j < 3 - sdim; j++) dxm++;
1823     tmp = *dxm++ - starts[0];
1824     for (j = 0; j < sdim - 1; j++) {
1825       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1826       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
1827     }
1828     dxm++;
1829     jdxm[i] = tmp;
1830   }
1831   for (i = 0; i < n; i++) {
1832     for (j = 0; j < 3 - sdim; j++) dxn++;
1833     tmp = *dxn++ - starts[0];
1834     for (j = 0; j < sdim - 1; j++) {
1835       if ((*dxn++ - starts[j + 1]) < 0 || tmp < 0) tmp = -1;
1836       else tmp = tmp * dims[j] + *(dxn - 1) - starts[j + 1];
1837     }
1838     dxn++;
1839     jdxn[i] = tmp;
1840   }
1841   PetscCall(MatSetValuesBlockedLocal(mat, m, jdxm, n, jdxn, v, addv));
1842   PetscCall(PetscFree2(bufm, bufn));
1843   PetscFunctionReturn(PETSC_SUCCESS);
1844 }
1845 
1846 /*@
1847    MatSetStencil - Sets the grid information for setting values into a matrix via
1848         `MatSetValuesStencil()`
1849 
1850    Not Collective
1851 
1852    Input Parameters:
1853 +  mat - the matrix
1854 .  dim - dimension of the grid 1, 2, or 3
1855 .  dims - number of grid points in x, y, and z direction, including ghost points on your processor
1856 .  starts - starting point of ghost nodes on your processor in x, y, and z direction
1857 -  dof - number of degrees of freedom per node
1858 
1859    Level: beginner
1860 
1861    Notes:
1862    Inspired by the structured grid interface to the HYPRE package
1863    (www.llnl.gov/CASC/hyper)
1864 
1865    For matrices generated with `DMCreateMatrix()` this routine is automatically called and so not needed by the
1866    user.
1867 
1868 .seealso: [](chapter_matrices), `Mat`, `MatStencil`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`
1869           `MatSetValues()`, `MatSetValuesBlockedStencil()`, `MatSetValuesStencil()`
1870 @*/
1871 PetscErrorCode MatSetStencil(Mat mat, PetscInt dim, const PetscInt dims[], const PetscInt starts[], PetscInt dof)
1872 {
1873   PetscFunctionBegin;
1874   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1875   PetscValidIntPointer(dims, 3);
1876   PetscValidIntPointer(starts, 4);
1877 
1878   mat->stencil.dim = dim + (dof > 1);
1879   for (PetscInt i = 0; i < dim; i++) {
1880     mat->stencil.dims[i]   = dims[dim - i - 1]; /* copy the values in backwards */
1881     mat->stencil.starts[i] = starts[dim - i - 1];
1882   }
1883   mat->stencil.dims[dim]   = dof;
1884   mat->stencil.starts[dim] = 0;
1885   mat->stencil.noc         = (PetscBool)(dof == 1);
1886   PetscFunctionReturn(PETSC_SUCCESS);
1887 }
1888 
1889 /*@C
1890    MatSetValuesBlocked - Inserts or adds a block of values into a matrix.
1891 
1892    Not Collective
1893 
1894    Input Parameters:
1895 +  mat - the matrix
1896 .  v - a logically two-dimensional array of values
1897 .  m  - the number of block rows
1898 .  idxm - the global block indices
1899 .  n - the number of block columns
1900 .  idxn - the global block indices
1901 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` replaces existing entries with new values
1902 
1903    Level: intermediate
1904 
1905    Notes:
1906    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call
1907    MatXXXXSetPreallocation() or `MatSetUp()` before using this routine.
1908 
1909    The `m` and `n` count the NUMBER of blocks in the row direction and column direction,
1910    NOT the total number of rows/columns; for example, if the block size is 2 and
1911    you are passing in values for rows 2,3,4,5  then m would be 2 (not 4).
1912    The values in idxm would be 1 2; that is the first index for each block divided by
1913    the block size.
1914 
1915    You must call `MatSetBlockSize()` when constructing this matrix (before
1916    preallocating it).
1917 
1918    By default the values, `v`, are row-oriented, so the layout of
1919    `v` is the same as for `MatSetValues()`. See `MatSetOption()` for other options.
1920 
1921    Calls to `MatSetValuesBlocked()` with the `INSERT_VALUES` and `ADD_VALUES`
1922    options cannot be mixed without intervening calls to the assembly
1923    routines.
1924 
1925    `MatSetValuesBlocked()` uses 0-based row and column numbers in Fortran
1926    as well as in C.
1927 
1928    Negative indices may be passed in `idxm` and `idxn`, these rows and columns are
1929    simply ignored. This allows easily inserting element stiffness matrices
1930    with homogeneous Dirchlet boundary conditions that you don't want represented
1931    in the matrix.
1932 
1933    Each time an entry is set within a sparse matrix via `MatSetValues()`,
1934    internal searching must be done to determine where to place the
1935    data in the matrix storage space.  By instead inserting blocks of
1936    entries via `MatSetValuesBlocked()`, the overhead of matrix assembly is
1937    reduced.
1938 
1939    Example:
1940 .vb
1941    Suppose m=n=2 and block size(bs) = 2 The array is
1942 
1943    1  2  | 3  4
1944    5  6  | 7  8
1945    - - - | - - -
1946    9  10 | 11 12
1947    13 14 | 15 16
1948 
1949    v[] should be passed in like
1950    v[] = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
1951 
1952   If you are not using row oriented storage of v (that is you called MatSetOption(mat,MAT_ROW_ORIENTED,PETSC_FALSE)) then
1953    v[] = [1,5,9,13,2,6,10,14,3,7,11,15,4,8,12,16]
1954 .ve
1955 
1956 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesBlockedLocal()`
1957 @*/
1958 PetscErrorCode MatSetValuesBlocked(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], const PetscScalar v[], InsertMode addv)
1959 {
1960   PetscFunctionBeginHot;
1961   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
1962   PetscValidType(mat, 1);
1963   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
1964   PetscValidIntPointer(idxm, 3);
1965   PetscValidIntPointer(idxn, 5);
1966   MatCheckPreallocated(mat, 1);
1967   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
1968   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
1969   if (PetscDefined(USE_DEBUG)) {
1970     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
1971     PetscCheck(mat->ops->setvaluesblocked || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
1972   }
1973   if (PetscDefined(USE_DEBUG)) {
1974     PetscInt rbs, cbs, M, N, i;
1975     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
1976     PetscCall(MatGetSize(mat, &M, &N));
1977     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);
1978     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);
1979   }
1980   if (mat->assembled) {
1981     mat->was_assembled = PETSC_TRUE;
1982     mat->assembled     = PETSC_FALSE;
1983   }
1984   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
1985   if (mat->ops->setvaluesblocked) {
1986     PetscUseTypeMethod(mat, setvaluesblocked, m, idxm, n, idxn, v, addv);
1987   } else {
1988     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *iidxm, *iidxn;
1989     PetscInt i, j, bs, cbs;
1990 
1991     PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
1992     if (m * bs + n * cbs <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
1993       iidxm = buf;
1994       iidxn = buf + m * bs;
1995     } else {
1996       PetscCall(PetscMalloc2(m * bs, &bufr, n * cbs, &bufc));
1997       iidxm = bufr;
1998       iidxn = bufc;
1999     }
2000     for (i = 0; i < m; i++) {
2001       for (j = 0; j < bs; j++) iidxm[i * bs + j] = bs * idxm[i] + j;
2002     }
2003     if (m != n || bs != cbs || idxm != idxn) {
2004       for (i = 0; i < n; i++) {
2005         for (j = 0; j < cbs; j++) iidxn[i * cbs + j] = cbs * idxn[i] + j;
2006       }
2007     } else iidxn = iidxm;
2008     PetscCall(MatSetValues(mat, m * bs, iidxm, n * cbs, iidxn, v, addv));
2009     PetscCall(PetscFree2(bufr, bufc));
2010   }
2011   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2012   PetscFunctionReturn(PETSC_SUCCESS);
2013 }
2014 
2015 /*@C
2016    MatGetValues - Gets a block of local values from a matrix.
2017 
2018    Not Collective; can only return values that are owned by the give process
2019 
2020    Input Parameters:
2021 +  mat - the matrix
2022 .  v - a logically two-dimensional array for storing the values
2023 .  m  - the number of rows
2024 .  idxm - the  global indices of the rows
2025 .  n - the number of columns
2026 -  idxn - the global indices of the columns
2027 
2028    Level: advanced
2029 
2030    Notes:
2031      The user must allocate space (m*n `PetscScalar`s) for the values, `v`.
2032      The values, `v`, are then returned in a row-oriented format,
2033      analogous to that used by default in `MatSetValues()`.
2034 
2035      `MatGetValues()` uses 0-based row and column numbers in
2036      Fortran as well as in C.
2037 
2038      `MatGetValues()` requires that the matrix has been assembled
2039      with `MatAssemblyBegin()`/`MatAssemblyEnd()`.  Thus, calls to
2040      `MatSetValues()` and `MatGetValues()` CANNOT be made in succession
2041      without intermediate matrix assembly.
2042 
2043      Negative row or column indices will be ignored and those locations in `v` will be
2044      left unchanged.
2045 
2046      For the standard row-based matrix formats, `idxm` can only contain rows owned by the requesting MPI rank.
2047      That is, rows with global index greater than or equal to rstart and less than rend where rstart and rend are obtainable
2048      from `MatGetOwnershipRange`(mat,&rstart,&rend).
2049 
2050 .seealso: [](chapter_matrices), `Mat`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatSetValues()`, `MatGetOwnershipRange()`, `MatGetValuesLocal()`, `MatGetValue()`
2051 @*/
2052 PetscErrorCode MatGetValues(Mat mat, PetscInt m, const PetscInt idxm[], PetscInt n, const PetscInt idxn[], PetscScalar v[])
2053 {
2054   PetscFunctionBegin;
2055   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2056   PetscValidType(mat, 1);
2057   if (!m || !n) PetscFunctionReturn(PETSC_SUCCESS);
2058   PetscValidIntPointer(idxm, 3);
2059   PetscValidIntPointer(idxn, 5);
2060   PetscValidScalarPointer(v, 6);
2061   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2062   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2063   MatCheckPreallocated(mat, 1);
2064 
2065   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2066   PetscUseTypeMethod(mat, getvalues, m, idxm, n, idxn, v);
2067   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2068   PetscFunctionReturn(PETSC_SUCCESS);
2069 }
2070 
2071 /*@C
2072    MatGetValuesLocal - retrieves values from certain locations in a matrix using the local numbering of the indices
2073      defined previously by `MatSetLocalToGlobalMapping()`
2074 
2075    Not Collective
2076 
2077    Input Parameters:
2078 +  mat - the matrix
2079 .  nrow - number of rows
2080 .  irow - the row local indices
2081 .  ncol - number of columns
2082 -  icol - the column local indices
2083 
2084    Output Parameter:
2085 .  y -  a logically two-dimensional array of values
2086 
2087    Level: advanced
2088 
2089    Notes:
2090      If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine.
2091 
2092      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,
2093      are greater than or equal to rstart and less than rend where rstart and rend are obtainable from `MatGetOwnershipRange`(mat,&rstart,&rend). One can
2094      determine if the resulting global row associated with the local row r is owned by the requesting MPI rank by applying the `ISLocalToGlobalMapping` set
2095      with `MatSetLocalToGlobalMapping()`.
2096 
2097    Developer Note:
2098       This is labelled with C so does not automatically generate Fortran stubs and interfaces
2099       because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2100 
2101 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2102           `MatSetValuesLocal()`, `MatGetValues()`
2103 @*/
2104 PetscErrorCode MatGetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], PetscScalar y[])
2105 {
2106   PetscFunctionBeginHot;
2107   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2108   PetscValidType(mat, 1);
2109   MatCheckPreallocated(mat, 1);
2110   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to retrieve */
2111   PetscValidIntPointer(irow, 3);
2112   PetscValidIntPointer(icol, 5);
2113   if (PetscDefined(USE_DEBUG)) {
2114     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2115     PetscCheck(mat->ops->getvalueslocal || mat->ops->getvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2116   }
2117   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2118   PetscCall(PetscLogEventBegin(MAT_GetValues, mat, 0, 0, 0));
2119   if (mat->ops->getvalueslocal) PetscUseTypeMethod(mat, getvalueslocal, nrow, irow, ncol, icol, y);
2120   else {
2121     PetscInt buf[8192], *bufr = NULL, *bufc = NULL, *irowm, *icolm;
2122     if ((nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2123       irowm = buf;
2124       icolm = buf + nrow;
2125     } else {
2126       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2127       irowm = bufr;
2128       icolm = bufc;
2129     }
2130     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global row mapping (See MatSetLocalToGlobalMapping()).");
2131     PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MatGetValuesLocal() cannot proceed without local-to-global column mapping (See MatSetLocalToGlobalMapping()).");
2132     PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, irowm));
2133     PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, icolm));
2134     PetscCall(MatGetValues(mat, nrow, irowm, ncol, icolm, y));
2135     PetscCall(PetscFree2(bufr, bufc));
2136   }
2137   PetscCall(PetscLogEventEnd(MAT_GetValues, mat, 0, 0, 0));
2138   PetscFunctionReturn(PETSC_SUCCESS);
2139 }
2140 
2141 /*@
2142   MatSetValuesBatch - Adds (`ADD_VALUES`) many blocks of values into a matrix at once. The blocks must all be square and
2143   the same size. Currently, this can only be called once and creates the given matrix.
2144 
2145   Not Collective
2146 
2147   Input Parameters:
2148 + mat - the matrix
2149 . nb - the number of blocks
2150 . bs - the number of rows (and columns) in each block
2151 . rows - a concatenation of the rows for each block
2152 - v - a concatenation of logically two-dimensional arrays of values
2153 
2154   Level: advanced
2155 
2156   Note:
2157   `MatSetPreallocationCOO()` and `MatSetValuesCOO()` may be a better way to provide the values
2158 
2159   In the future, we will extend this routine to handle rectangular blocks, and to allow multiple calls for a given matrix.
2160 
2161 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValuesBlocked()`, `MatSetValuesLocal()`,
2162           `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `MatSetValues()`, `MatSetPreallocationCOO()`, `MatSetValuesCOO()`
2163 @*/
2164 PetscErrorCode MatSetValuesBatch(Mat mat, PetscInt nb, PetscInt bs, PetscInt rows[], const PetscScalar v[])
2165 {
2166   PetscFunctionBegin;
2167   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2168   PetscValidType(mat, 1);
2169   PetscValidIntPointer(rows, 4);
2170   PetscValidScalarPointer(v, 5);
2171   PetscAssert(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2172 
2173   PetscCall(PetscLogEventBegin(MAT_SetValuesBatch, mat, 0, 0, 0));
2174   if (mat->ops->setvaluesbatch) PetscUseTypeMethod(mat, setvaluesbatch, nb, bs, rows, v);
2175   else {
2176     for (PetscInt b = 0; b < nb; ++b) PetscCall(MatSetValues(mat, bs, &rows[b * bs], bs, &rows[b * bs], &v[b * bs * bs], ADD_VALUES));
2177   }
2178   PetscCall(PetscLogEventEnd(MAT_SetValuesBatch, mat, 0, 0, 0));
2179   PetscFunctionReturn(PETSC_SUCCESS);
2180 }
2181 
2182 /*@
2183    MatSetLocalToGlobalMapping - Sets a local-to-global numbering for use by
2184    the routine `MatSetValuesLocal()` to allow users to insert matrix entries
2185    using a local (per-processor) numbering.
2186 
2187    Not Collective
2188 
2189    Input Parameters:
2190 +  x - the matrix
2191 .  rmapping - row mapping created with `ISLocalToGlobalMappingCreate()` or `ISLocalToGlobalMappingCreateIS()`
2192 -  cmapping - column mapping
2193 
2194    Level: intermediate
2195 
2196    Note:
2197    If the matrix is obtained with `DMCreateMatrix()` then this may already have been called on the matrix
2198 
2199 .seealso: [](chapter_matrices), `Mat`, `DM`, `DMCreateMatrix()`, `MatGetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetValuesLocal()`, `MatGetValuesLocal()`
2200 @*/
2201 PetscErrorCode MatSetLocalToGlobalMapping(Mat x, ISLocalToGlobalMapping rmapping, ISLocalToGlobalMapping cmapping)
2202 {
2203   PetscFunctionBegin;
2204   PetscValidHeaderSpecific(x, MAT_CLASSID, 1);
2205   PetscValidType(x, 1);
2206   if (rmapping) PetscValidHeaderSpecific(rmapping, IS_LTOGM_CLASSID, 2);
2207   if (cmapping) PetscValidHeaderSpecific(cmapping, IS_LTOGM_CLASSID, 3);
2208   if (x->ops->setlocaltoglobalmapping) PetscUseTypeMethod(x, setlocaltoglobalmapping, rmapping, cmapping);
2209   else {
2210     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->rmap, rmapping));
2211     PetscCall(PetscLayoutSetISLocalToGlobalMapping(x->cmap, cmapping));
2212   }
2213   PetscFunctionReturn(PETSC_SUCCESS);
2214 }
2215 
2216 /*@
2217    MatGetLocalToGlobalMapping - Gets the local-to-global numbering set by `MatSetLocalToGlobalMapping()`
2218 
2219    Not Collective
2220 
2221    Input Parameter:
2222 .  A - the matrix
2223 
2224    Output Parameters:
2225 + rmapping - row mapping
2226 - cmapping - column mapping
2227 
2228    Level: advanced
2229 
2230 .seealso: [](chapter_matrices), `Mat`, `MatSetLocalToGlobalMapping()`, `MatSetValuesLocal()`
2231 @*/
2232 PetscErrorCode MatGetLocalToGlobalMapping(Mat A, ISLocalToGlobalMapping *rmapping, ISLocalToGlobalMapping *cmapping)
2233 {
2234   PetscFunctionBegin;
2235   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2236   PetscValidType(A, 1);
2237   if (rmapping) {
2238     PetscValidPointer(rmapping, 2);
2239     *rmapping = A->rmap->mapping;
2240   }
2241   if (cmapping) {
2242     PetscValidPointer(cmapping, 3);
2243     *cmapping = A->cmap->mapping;
2244   }
2245   PetscFunctionReturn(PETSC_SUCCESS);
2246 }
2247 
2248 /*@
2249    MatSetLayouts - Sets the `PetscLayout` objects for rows and columns of a matrix
2250 
2251    Logically Collective
2252 
2253    Input Parameters:
2254 +  A - the matrix
2255 . rmap - row layout
2256 - cmap - column layout
2257 
2258    Level: advanced
2259 
2260    Note:
2261    The `PetscLayout` objects are usually created automatically for the matrix so this routine rarely needs to be called.
2262 
2263 .seealso: [](chapter_matrices), `Mat`, `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatGetLayouts()`
2264 @*/
2265 PetscErrorCode MatSetLayouts(Mat A, PetscLayout rmap, PetscLayout cmap)
2266 {
2267   PetscFunctionBegin;
2268   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2269   PetscCall(PetscLayoutReference(rmap, &A->rmap));
2270   PetscCall(PetscLayoutReference(cmap, &A->cmap));
2271   PetscFunctionReturn(PETSC_SUCCESS);
2272 }
2273 
2274 /*@
2275    MatGetLayouts - Gets the `PetscLayout` objects for rows and columns
2276 
2277    Not Collective
2278 
2279    Input Parameter:
2280 .  A - the matrix
2281 
2282    Output Parameters:
2283 + rmap - row layout
2284 - cmap - column layout
2285 
2286    Level: advanced
2287 
2288 .seealso: [](chapter_matrices), `Mat`, [Matrix Layouts](sec_matlayout), `PetscLayout`, `MatCreateVecs()`, `MatGetLocalToGlobalMapping()`, `MatSetLayouts()`
2289 @*/
2290 PetscErrorCode MatGetLayouts(Mat A, PetscLayout *rmap, PetscLayout *cmap)
2291 {
2292   PetscFunctionBegin;
2293   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
2294   PetscValidType(A, 1);
2295   if (rmap) {
2296     PetscValidPointer(rmap, 2);
2297     *rmap = A->rmap;
2298   }
2299   if (cmap) {
2300     PetscValidPointer(cmap, 3);
2301     *cmap = A->cmap;
2302   }
2303   PetscFunctionReturn(PETSC_SUCCESS);
2304 }
2305 
2306 /*@C
2307    MatSetValuesLocal - Inserts or adds values into certain locations of a matrix,
2308    using a local numbering of the nodes.
2309 
2310    Not Collective
2311 
2312    Input Parameters:
2313 +  mat - the matrix
2314 .  nrow - number of rows
2315 .  irow - the row local indices
2316 .  ncol - number of columns
2317 .  icol - the column local indices
2318 .  y -  a logically two-dimensional array of values
2319 -  addv - either `INSERT_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2320 
2321    Level: intermediate
2322 
2323    Notes:
2324    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2325       `MatSetUp()` before using this routine
2326 
2327    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetLocalToGlobalMapping()` before using this routine
2328 
2329    Calls to `MatSetValuesLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2330    options cannot be mixed without intervening calls to the assembly
2331    routines.
2332 
2333    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2334    MUST be called after all calls to `MatSetValuesLocal()` have been completed.
2335 
2336    Developer Note:
2337     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2338                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2339 
2340 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatAssemblyEnd()`, `MatSetValues()`, `MatSetLocalToGlobalMapping()`,
2341           `MatGetValuesLocal()`
2342 @*/
2343 PetscErrorCode MatSetValuesLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2344 {
2345   PetscFunctionBeginHot;
2346   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2347   PetscValidType(mat, 1);
2348   MatCheckPreallocated(mat, 1);
2349   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2350   PetscValidIntPointer(irow, 3);
2351   PetscValidIntPointer(icol, 5);
2352   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2353   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2354   if (PetscDefined(USE_DEBUG)) {
2355     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2356     PetscCheck(mat->ops->setvalueslocal || mat->ops->setvalues, PETSC_COMM_SELF, PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2357   }
2358 
2359   if (mat->assembled) {
2360     mat->was_assembled = PETSC_TRUE;
2361     mat->assembled     = PETSC_FALSE;
2362   }
2363   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2364   if (mat->ops->setvalueslocal) PetscUseTypeMethod(mat, setvalueslocal, nrow, irow, ncol, icol, y, addv);
2365   else {
2366     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2367     const PetscInt *irowm, *icolm;
2368 
2369     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2370       bufr  = buf;
2371       bufc  = buf + nrow;
2372       irowm = bufr;
2373       icolm = bufc;
2374     } else {
2375       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2376       irowm = bufr;
2377       icolm = bufc;
2378     }
2379     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApply(mat->rmap->mapping, nrow, irow, bufr));
2380     else irowm = irow;
2381     if (mat->cmap->mapping) {
2382       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2383         PetscCall(ISLocalToGlobalMappingApply(mat->cmap->mapping, ncol, icol, bufc));
2384       } else icolm = irowm;
2385     } else icolm = icol;
2386     PetscCall(MatSetValues(mat, nrow, irowm, ncol, icolm, y, addv));
2387     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2388   }
2389   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2390   PetscFunctionReturn(PETSC_SUCCESS);
2391 }
2392 
2393 /*@C
2394    MatSetValuesBlockedLocal - Inserts or adds values into certain locations of a matrix,
2395    using a local ordering of the nodes a block at a time.
2396 
2397    Not Collective
2398 
2399    Input Parameters:
2400 +  x - the matrix
2401 .  nrow - number of rows
2402 .  irow - the row local indices
2403 .  ncol - number of columns
2404 .  icol - the column local indices
2405 .  y -  a logically two-dimensional array of values
2406 -  addv - either `ADD_VALUES` to add values to any existing entries, or `INSERT_VALUES` to replace existing entries with new values
2407 
2408    Level: intermediate
2409 
2410    Notes:
2411    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call MatXXXXSetPreallocation() or
2412       `MatSetUp()` before using this routine
2413 
2414    If you create the matrix yourself (that is not with a call to `DMCreateMatrix()`) then you MUST call `MatSetBlockSize()` and `MatSetLocalToGlobalMapping()`
2415       before using this routineBefore calling `MatSetValuesLocal()`, the user must first set the
2416 
2417    Calls to `MatSetValuesBlockedLocal()` with the `INSERT_VALUES` and `ADD_VALUES`
2418    options cannot be mixed without intervening calls to the assembly
2419    routines.
2420 
2421    These values may be cached, so `MatAssemblyBegin()` and `MatAssemblyEnd()`
2422    MUST be called after all calls to `MatSetValuesBlockedLocal()` have been completed.
2423 
2424    Developer Note:
2425     This is labeled with C so does not automatically generate Fortran stubs and interfaces
2426                     because it requires multiple Fortran interfaces depending on which arguments are scalar or arrays.
2427 
2428 .seealso: [](chapter_matrices), `Mat`, `MatSetBlockSize()`, `MatSetLocalToGlobalMapping()`, `MatAssemblyBegin()`, `MatAssemblyEnd()`,
2429           `MatSetValuesLocal()`, `MatSetValuesBlocked()`
2430 @*/
2431 PetscErrorCode MatSetValuesBlockedLocal(Mat mat, PetscInt nrow, const PetscInt irow[], PetscInt ncol, const PetscInt icol[], const PetscScalar y[], InsertMode addv)
2432 {
2433   PetscFunctionBeginHot;
2434   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2435   PetscValidType(mat, 1);
2436   MatCheckPreallocated(mat, 1);
2437   if (!nrow || !ncol) PetscFunctionReturn(PETSC_SUCCESS); /* no values to insert */
2438   PetscValidIntPointer(irow, 3);
2439   PetscValidIntPointer(icol, 5);
2440   if (mat->insertmode == NOT_SET_VALUES) mat->insertmode = addv;
2441   else PetscCheck(mat->insertmode == addv, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Cannot mix add values and insert values");
2442   if (PetscDefined(USE_DEBUG)) {
2443     PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2444     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);
2445   }
2446 
2447   if (mat->assembled) {
2448     mat->was_assembled = PETSC_TRUE;
2449     mat->assembled     = PETSC_FALSE;
2450   }
2451   if (PetscUnlikelyDebug(mat->rmap->mapping)) { /* Condition on the mapping existing, because MatSetValuesBlockedLocal_IS does not require it to be set. */
2452     PetscInt irbs, rbs;
2453     PetscCall(MatGetBlockSizes(mat, &rbs, NULL));
2454     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping, &irbs));
2455     PetscCheck(rbs == irbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different row block sizes! mat %" PetscInt_FMT ", row l2g map %" PetscInt_FMT, rbs, irbs);
2456   }
2457   if (PetscUnlikelyDebug(mat->cmap->mapping)) {
2458     PetscInt icbs, cbs;
2459     PetscCall(MatGetBlockSizes(mat, NULL, &cbs));
2460     PetscCall(ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping, &icbs));
2461     PetscCheck(cbs == icbs, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Different col block sizes! mat %" PetscInt_FMT ", col l2g map %" PetscInt_FMT, cbs, icbs);
2462   }
2463   PetscCall(PetscLogEventBegin(MAT_SetValues, mat, 0, 0, 0));
2464   if (mat->ops->setvaluesblockedlocal) PetscUseTypeMethod(mat, setvaluesblockedlocal, nrow, irow, ncol, icol, y, addv);
2465   else {
2466     PetscInt        buf[8192], *bufr = NULL, *bufc = NULL;
2467     const PetscInt *irowm, *icolm;
2468 
2469     if ((!mat->rmap->mapping && !mat->cmap->mapping) || (nrow + ncol) <= (PetscInt)(sizeof(buf) / sizeof(PetscInt))) {
2470       bufr  = buf;
2471       bufc  = buf + nrow;
2472       irowm = bufr;
2473       icolm = bufc;
2474     } else {
2475       PetscCall(PetscMalloc2(nrow, &bufr, ncol, &bufc));
2476       irowm = bufr;
2477       icolm = bufc;
2478     }
2479     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingApplyBlock(mat->rmap->mapping, nrow, irow, bufr));
2480     else irowm = irow;
2481     if (mat->cmap->mapping) {
2482       if (mat->cmap->mapping != mat->rmap->mapping || ncol != nrow || icol != irow) {
2483         PetscCall(ISLocalToGlobalMappingApplyBlock(mat->cmap->mapping, ncol, icol, bufc));
2484       } else icolm = irowm;
2485     } else icolm = icol;
2486     PetscCall(MatSetValuesBlocked(mat, nrow, irowm, ncol, icolm, y, addv));
2487     if (bufr != buf) PetscCall(PetscFree2(bufr, bufc));
2488   }
2489   PetscCall(PetscLogEventEnd(MAT_SetValues, mat, 0, 0, 0));
2490   PetscFunctionReturn(PETSC_SUCCESS);
2491 }
2492 
2493 /*@
2494    MatMultDiagonalBlock - Computes the matrix-vector product, y = Dx. Where D is defined by the inode or block structure of the diagonal
2495 
2496    Collective
2497 
2498    Input Parameters:
2499 +  mat - the matrix
2500 -  x   - the vector to be multiplied
2501 
2502    Output Parameter:
2503 .  y - the result
2504 
2505    Level: developer
2506 
2507    Note:
2508    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2509    call `MatMultDiagonalBlock`(A,y,y).
2510 
2511 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2512 @*/
2513 PetscErrorCode MatMultDiagonalBlock(Mat mat, Vec x, Vec y)
2514 {
2515   PetscFunctionBegin;
2516   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2517   PetscValidType(mat, 1);
2518   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2519   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2520 
2521   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2522   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2523   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2524   MatCheckPreallocated(mat, 1);
2525 
2526   PetscUseTypeMethod(mat, multdiagonalblock, x, y);
2527   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2528   PetscFunctionReturn(PETSC_SUCCESS);
2529 }
2530 
2531 /*@
2532    MatMult - Computes the matrix-vector product, y = Ax.
2533 
2534    Neighbor-wise Collective
2535 
2536    Input Parameters:
2537 +  mat - the matrix
2538 -  x   - the vector to be multiplied
2539 
2540    Output Parameter:
2541 .  y - the result
2542 
2543    Level: beginner
2544 
2545    Note:
2546    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2547    call `MatMult`(A,y,y).
2548 
2549 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
2550 @*/
2551 PetscErrorCode MatMult(Mat mat, Vec x, Vec y)
2552 {
2553   PetscFunctionBegin;
2554   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2555   PetscValidType(mat, 1);
2556   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2557   VecCheckAssembled(x);
2558   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2559   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2560   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2561   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2562   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);
2563   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);
2564   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);
2565   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);
2566   PetscCall(VecSetErrorIfLocked(y, 3));
2567   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2568   MatCheckPreallocated(mat, 1);
2569 
2570   PetscCall(VecLockReadPush(x));
2571   PetscCall(PetscLogEventBegin(MAT_Mult, mat, x, y, 0));
2572   PetscUseTypeMethod(mat, mult, x, y);
2573   PetscCall(PetscLogEventEnd(MAT_Mult, mat, x, y, 0));
2574   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2575   PetscCall(VecLockReadPop(x));
2576   PetscFunctionReturn(PETSC_SUCCESS);
2577 }
2578 
2579 /*@
2580    MatMultTranspose - Computes matrix transpose times a vector y = A^T * x.
2581 
2582    Neighbor-wise Collective
2583 
2584    Input Parameters:
2585 +  mat - the matrix
2586 -  x   - the vector to be multiplied
2587 
2588    Output Parameter:
2589 .  y - the result
2590 
2591    Level: beginner
2592 
2593    Notes:
2594    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2595    call `MatMultTranspose`(A,y,y).
2596 
2597    For complex numbers this does NOT compute the Hermitian (complex conjugate) transpose multiple,
2598    use `MatMultHermitianTranspose()`
2599 
2600 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatMultHermitianTranspose()`, `MatTranspose()`
2601 @*/
2602 PetscErrorCode MatMultTranspose(Mat mat, Vec x, Vec y)
2603 {
2604   PetscErrorCode (*op)(Mat, Vec, Vec) = NULL;
2605 
2606   PetscFunctionBegin;
2607   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2608   PetscValidType(mat, 1);
2609   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2610   VecCheckAssembled(x);
2611   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2612 
2613   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2614   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2615   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2616   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);
2617   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);
2618   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);
2619   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);
2620   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(x, 2, PETSC_TRUE));
2621   MatCheckPreallocated(mat, 1);
2622 
2623   if (!mat->ops->multtranspose) {
2624     if (mat->symmetric == PETSC_BOOL3_TRUE && mat->ops->mult) op = mat->ops->mult;
2625     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);
2626   } else op = mat->ops->multtranspose;
2627   PetscCall(PetscLogEventBegin(MAT_MultTranspose, mat, x, y, 0));
2628   PetscCall(VecLockReadPush(x));
2629   PetscCall((*op)(mat, x, y));
2630   PetscCall(VecLockReadPop(x));
2631   PetscCall(PetscLogEventEnd(MAT_MultTranspose, mat, x, y, 0));
2632   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2633   if (mat->erroriffailure) PetscCall(VecValidValues_Internal(y, 3, PETSC_FALSE));
2634   PetscFunctionReturn(PETSC_SUCCESS);
2635 }
2636 
2637 /*@
2638    MatMultHermitianTranspose - Computes matrix Hermitian transpose times a vector.
2639 
2640    Neighbor-wise Collective
2641 
2642    Input Parameters:
2643 +  mat - the matrix
2644 -  x   - the vector to be multilplied
2645 
2646    Output Parameter:
2647 .  y - the result
2648 
2649    Level: beginner
2650 
2651    Notes:
2652    The vectors `x` and `y` cannot be the same.  I.e., one cannot
2653    call `MatMultHermitianTranspose`(A,y,y).
2654 
2655    Also called the conjugate transpose, complex conjugate transpose, or adjoint.
2656 
2657    For real numbers `MatMultTranspose()` and `MatMultHermitianTranspose()` are identical.
2658 
2659 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `MatMultHermitianTransposeAdd()`, `MatMultTranspose()`
2660 @*/
2661 PetscErrorCode MatMultHermitianTranspose(Mat mat, Vec x, Vec y)
2662 {
2663   PetscFunctionBegin;
2664   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2665   PetscValidType(mat, 1);
2666   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
2667   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
2668 
2669   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2670   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2671   PetscCheck(x != y, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "x and y must be different vectors");
2672   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);
2673   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);
2674   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);
2675   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);
2676   MatCheckPreallocated(mat, 1);
2677 
2678   PetscCall(PetscLogEventBegin(MAT_MultHermitianTranspose, mat, x, y, 0));
2679 #if defined(PETSC_USE_COMPLEX)
2680   if (mat->ops->multhermitiantranspose || (mat->hermitian == PETSC_BOOL3_TRUE && mat->ops->mult)) {
2681     PetscCall(VecLockReadPush(x));
2682     if (mat->ops->multhermitiantranspose) PetscUseTypeMethod(mat, multhermitiantranspose, x, y);
2683     else PetscUseTypeMethod(mat, mult, x, y);
2684     PetscCall(VecLockReadPop(x));
2685   } else {
2686     Vec w;
2687     PetscCall(VecDuplicate(x, &w));
2688     PetscCall(VecCopy(x, w));
2689     PetscCall(VecConjugate(w));
2690     PetscCall(MatMultTranspose(mat, w, y));
2691     PetscCall(VecDestroy(&w));
2692     PetscCall(VecConjugate(y));
2693   }
2694   PetscCall(PetscObjectStateIncrease((PetscObject)y));
2695 #else
2696   PetscCall(MatMultTranspose(mat, x, y));
2697 #endif
2698   PetscCall(PetscLogEventEnd(MAT_MultHermitianTranspose, mat, x, y, 0));
2699   PetscFunctionReturn(PETSC_SUCCESS);
2700 }
2701 
2702 /*@
2703     MatMultAdd -  Computes v3 = v2 + A * v1.
2704 
2705     Neighbor-wise Collective
2706 
2707     Input Parameters:
2708 +   mat - the matrix
2709 .   v1 - the vector to be multiplied by `mat`
2710 -   v2 - the vector to be added to the result
2711 
2712     Output Parameter:
2713 .   v3 - the result
2714 
2715     Level: beginner
2716 
2717     Note:
2718     The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2719     call `MatMultAdd`(A,v1,v2,v1).
2720 
2721 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMult()`, `MatMultTransposeAdd()`
2722 @*/
2723 PetscErrorCode MatMultAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2724 {
2725   PetscFunctionBegin;
2726   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2727   PetscValidType(mat, 1);
2728   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2729   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2730   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2731 
2732   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2733   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2734   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);
2735   /* 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);
2736      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); */
2737   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);
2738   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);
2739   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2740   MatCheckPreallocated(mat, 1);
2741 
2742   PetscCall(PetscLogEventBegin(MAT_MultAdd, mat, v1, v2, v3));
2743   PetscCall(VecLockReadPush(v1));
2744   PetscUseTypeMethod(mat, multadd, v1, v2, v3);
2745   PetscCall(VecLockReadPop(v1));
2746   PetscCall(PetscLogEventEnd(MAT_MultAdd, mat, v1, v2, v3));
2747   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2748   PetscFunctionReturn(PETSC_SUCCESS);
2749 }
2750 
2751 /*@
2752    MatMultTransposeAdd - Computes v3 = v2 + A' * v1.
2753 
2754    Neighbor-wise Collective
2755 
2756    Input Parameters:
2757 +  mat - the matrix
2758 .  v1 - the vector to be multiplied by the transpose of the matrix
2759 -  v2 - the vector to be added to the result
2760 
2761    Output Parameter:
2762 .  v3 - the result
2763 
2764    Level: beginner
2765 
2766    Note:
2767    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2768    call `MatMultTransposeAdd`(A,v1,v2,v1).
2769 
2770 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2771 @*/
2772 PetscErrorCode MatMultTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2773 {
2774   PetscErrorCode (*op)(Mat, Vec, Vec, Vec) = (!mat->ops->multtransposeadd && mat->symmetric) ? mat->ops->multadd : mat->ops->multtransposeadd;
2775 
2776   PetscFunctionBegin;
2777   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2778   PetscValidType(mat, 1);
2779   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2780   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2781   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2782 
2783   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2784   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2785   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);
2786   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);
2787   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);
2788   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2789   PetscCheck(op, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)mat)->type_name);
2790   MatCheckPreallocated(mat, 1);
2791 
2792   PetscCall(PetscLogEventBegin(MAT_MultTransposeAdd, mat, v1, v2, v3));
2793   PetscCall(VecLockReadPush(v1));
2794   PetscCall((*op)(mat, v1, v2, v3));
2795   PetscCall(VecLockReadPop(v1));
2796   PetscCall(PetscLogEventEnd(MAT_MultTransposeAdd, mat, v1, v2, v3));
2797   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2798   PetscFunctionReturn(PETSC_SUCCESS);
2799 }
2800 
2801 /*@
2802    MatMultHermitianTransposeAdd - Computes v3 = v2 + A^H * v1.
2803 
2804    Neighbor-wise Collective
2805 
2806    Input Parameters:
2807 +  mat - the matrix
2808 .  v1 - the vector to be multiplied by the Hermitian transpose
2809 -  v2 - the vector to be added to the result
2810 
2811    Output Parameter:
2812 .  v3 - the result
2813 
2814    Level: beginner
2815 
2816    Note:
2817    The vectors `v1` and `v3` cannot be the same.  I.e., one cannot
2818    call `MatMultHermitianTransposeAdd`(A,v1,v2,v1).
2819 
2820 .seealso: [](chapter_matrices), `Mat`, `MatMultHermitianTranspose()`, `MatMultTranspose()`, `MatMultAdd()`, `MatMult()`
2821 @*/
2822 PetscErrorCode MatMultHermitianTransposeAdd(Mat mat, Vec v1, Vec v2, Vec v3)
2823 {
2824   PetscFunctionBegin;
2825   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2826   PetscValidType(mat, 1);
2827   PetscValidHeaderSpecific(v1, VEC_CLASSID, 2);
2828   PetscValidHeaderSpecific(v2, VEC_CLASSID, 3);
2829   PetscValidHeaderSpecific(v3, VEC_CLASSID, 4);
2830 
2831   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
2832   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
2833   PetscCheck(v1 != v3, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "v1 and v3 must be different vectors");
2834   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);
2835   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);
2836   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);
2837   MatCheckPreallocated(mat, 1);
2838 
2839   PetscCall(PetscLogEventBegin(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2840   PetscCall(VecLockReadPush(v1));
2841   if (mat->ops->multhermitiantransposeadd) PetscUseTypeMethod(mat, multhermitiantransposeadd, v1, v2, v3);
2842   else {
2843     Vec w, z;
2844     PetscCall(VecDuplicate(v1, &w));
2845     PetscCall(VecCopy(v1, w));
2846     PetscCall(VecConjugate(w));
2847     PetscCall(VecDuplicate(v3, &z));
2848     PetscCall(MatMultTranspose(mat, w, z));
2849     PetscCall(VecDestroy(&w));
2850     PetscCall(VecConjugate(z));
2851     if (v2 != v3) {
2852       PetscCall(VecWAXPY(v3, 1.0, v2, z));
2853     } else {
2854       PetscCall(VecAXPY(v3, 1.0, z));
2855     }
2856     PetscCall(VecDestroy(&z));
2857   }
2858   PetscCall(VecLockReadPop(v1));
2859   PetscCall(PetscLogEventEnd(MAT_MultHermitianTransposeAdd, mat, v1, v2, v3));
2860   PetscCall(PetscObjectStateIncrease((PetscObject)v3));
2861   PetscFunctionReturn(PETSC_SUCCESS);
2862 }
2863 
2864 /*@C
2865    MatGetFactorType - gets the type of factorization it is
2866 
2867    Not Collective
2868 
2869    Input Parameter:
2870 .  mat - the matrix
2871 
2872    Output Parameter:
2873 .  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`
2874 
2875    Level: intermediate
2876 
2877 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatSetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2878           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2879 @*/
2880 PetscErrorCode MatGetFactorType(Mat mat, MatFactorType *t)
2881 {
2882   PetscFunctionBegin;
2883   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2884   PetscValidType(mat, 1);
2885   PetscValidPointer(t, 2);
2886   *t = mat->factortype;
2887   PetscFunctionReturn(PETSC_SUCCESS);
2888 }
2889 
2890 /*@C
2891    MatSetFactorType - sets the type of factorization it is
2892 
2893    Logically Collective
2894 
2895    Input Parameters:
2896 +  mat - the matrix
2897 -  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`
2898 
2899    Level: intermediate
2900 
2901 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatGetFactor()`, `MatGetFactorType()`, `MAT_FACTOR_NONE`, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ILU`,
2902           `MAT_FACTOR_ICC,MAT_FACTOR_ILUDT`, `MAT_FACTOR_QR`
2903 @*/
2904 PetscErrorCode MatSetFactorType(Mat mat, MatFactorType t)
2905 {
2906   PetscFunctionBegin;
2907   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2908   PetscValidType(mat, 1);
2909   mat->factortype = t;
2910   PetscFunctionReturn(PETSC_SUCCESS);
2911 }
2912 
2913 /*@C
2914    MatGetInfo - Returns information about matrix storage (number of
2915    nonzeros, memory, etc.).
2916 
2917    Collective if `MAT_GLOBAL_MAX` or `MAT_GLOBAL_SUM` is used as the flag
2918 
2919    Input Parameters:
2920 +  mat - the matrix
2921 -  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)
2922 
2923    Output Parameter:
2924 .  info - matrix information context
2925 
2926    Options Database Key:
2927 .  -mat_view ::ascii_info - print matrix info to `PETSC_STDOUT`
2928 
2929    Notes:
2930    The `MatInfo` context contains a variety of matrix data, including
2931    number of nonzeros allocated and used, number of mallocs during
2932    matrix assembly, etc.  Additional information for factored matrices
2933    is provided (such as the fill ratio, number of mallocs during
2934    factorization, etc.).
2935 
2936    Example:
2937    See the file ${PETSC_DIR}/include/petscmat.h for a complete list of
2938    data within the MatInfo context.  For example,
2939 .vb
2940       MatInfo info;
2941       Mat     A;
2942       double  mal, nz_a, nz_u;
2943 
2944       MatGetInfo(A, MAT_LOCAL, &info);
2945       mal  = info.mallocs;
2946       nz_a = info.nz_allocated;
2947 .ve
2948 
2949    Fortran users should declare info as a double precision
2950    array of dimension `MAT_INFO_SIZE`, and then extract the parameters
2951    of interest.  See the file ${PETSC_DIR}/include/petsc/finclude/petscmat.h
2952    a complete list of parameter names.
2953 .vb
2954       double  precision info(MAT_INFO_SIZE)
2955       double  precision mal, nz_a
2956       Mat     A
2957       integer ierr
2958 
2959       call MatGetInfo(A, MAT_LOCAL, info, ierr)
2960       mal = info(MAT_INFO_MALLOCS)
2961       nz_a = info(MAT_INFO_NZ_ALLOCATED)
2962 .ve
2963 
2964     Level: intermediate
2965 
2966     Developer Note:
2967     The Fortran interface is not autogenerated as the
2968     interface definition cannot be generated correctly [due to `MatInfo` argument]
2969 
2970 .seealso: [](chapter_matrices), `Mat`, `MatInfo`, `MatStashGetInfo()`
2971 @*/
2972 PetscErrorCode MatGetInfo(Mat mat, MatInfoType flag, MatInfo *info)
2973 {
2974   PetscFunctionBegin;
2975   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
2976   PetscValidType(mat, 1);
2977   PetscValidPointer(info, 3);
2978   MatCheckPreallocated(mat, 1);
2979   PetscUseTypeMethod(mat, getinfo, flag, info);
2980   PetscFunctionReturn(PETSC_SUCCESS);
2981 }
2982 
2983 /*
2984    This is used by external packages where it is not easy to get the info from the actual
2985    matrix factorization.
2986 */
2987 PetscErrorCode MatGetInfo_External(Mat A, MatInfoType flag, MatInfo *info)
2988 {
2989   PetscFunctionBegin;
2990   PetscCall(PetscMemzero(info, sizeof(MatInfo)));
2991   PetscFunctionReturn(PETSC_SUCCESS);
2992 }
2993 
2994 /*@C
2995    MatLUFactor - Performs in-place LU factorization of matrix.
2996 
2997    Collective
2998 
2999    Input Parameters:
3000 +  mat - the matrix
3001 .  row - row permutation
3002 .  col - column permutation
3003 -  info - options for factorization, includes
3004 .vb
3005           fill - expected fill as ratio of original fill.
3006           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3007                    Run with the option -info to determine an optimal value to use
3008 .ve
3009    Level: developer
3010 
3011    Notes:
3012    Most users should employ the `KSP` interface for linear solvers
3013    instead of working directly with matrix algebra routines such as this.
3014    See, e.g., `KSPCreate()`.
3015 
3016    This changes the state of the matrix to a factored matrix; it cannot be used
3017    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3018 
3019    This is really in-place only for dense matrices, the preferred approach is to use `MatGetFactor()`, `MatLUFactorSymbolic()`, and `MatLUFactorNumeric()`
3020    when not using `KSP`.
3021 
3022    Developer Note:
3023    The Fortran interface is not autogenerated as the
3024    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3025 
3026 .seealso: [](chapter_matrices), [Matrix Factorization](sec_matfactor), `Mat`, `MatFactorType`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`,
3027           `MatGetOrdering()`, `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3028 @*/
3029 PetscErrorCode MatLUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3030 {
3031   MatFactorInfo tinfo;
3032 
3033   PetscFunctionBegin;
3034   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3035   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3036   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3037   if (info) PetscValidPointer(info, 4);
3038   PetscValidType(mat, 1);
3039   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3040   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3041   MatCheckPreallocated(mat, 1);
3042   if (!info) {
3043     PetscCall(MatFactorInfoInitialize(&tinfo));
3044     info = &tinfo;
3045   }
3046 
3047   PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, row, col, 0));
3048   PetscUseTypeMethod(mat, lufactor, row, col, info);
3049   PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, row, col, 0));
3050   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3051   PetscFunctionReturn(PETSC_SUCCESS);
3052 }
3053 
3054 /*@C
3055    MatILUFactor - Performs in-place ILU factorization of matrix.
3056 
3057    Collective
3058 
3059    Input Parameters:
3060 +  mat - the matrix
3061 .  row - row permutation
3062 .  col - column permutation
3063 -  info - structure containing
3064 .vb
3065       levels - number of levels of fill.
3066       expected fill - as ratio of original fill.
3067       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
3068                 missing diagonal entries)
3069 .ve
3070 
3071    Level: developer
3072 
3073    Notes:
3074    Most users should employ the `KSP` interface for linear solvers
3075    instead of working directly with matrix algebra routines such as this.
3076    See, e.g., `KSPCreate()`.
3077 
3078    Probably really in-place only when level of fill is zero, otherwise allocates
3079    new space to store factored matrix and deletes previous memory. The preferred approach is to use `MatGetFactor()`, `MatILUFactorSymbolic()`, and `MatILUFactorNumeric()`
3080    when not using `KSP`.
3081 
3082    Developer Note:
3083    The Fortran interface is not autogenerated as the
3084    interface definition cannot be generated correctly [due to MatFactorInfo]
3085 
3086 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatILUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
3087 @*/
3088 PetscErrorCode MatILUFactor(Mat mat, IS row, IS col, const MatFactorInfo *info)
3089 {
3090   PetscFunctionBegin;
3091   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3092   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
3093   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3094   PetscValidPointer(info, 4);
3095   PetscValidType(mat, 1);
3096   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
3097   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3098   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3099   MatCheckPreallocated(mat, 1);
3100 
3101   PetscCall(PetscLogEventBegin(MAT_ILUFactor, mat, row, col, 0));
3102   PetscUseTypeMethod(mat, ilufactor, row, col, info);
3103   PetscCall(PetscLogEventEnd(MAT_ILUFactor, mat, row, col, 0));
3104   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3105   PetscFunctionReturn(PETSC_SUCCESS);
3106 }
3107 
3108 /*@C
3109    MatLUFactorSymbolic - Performs symbolic LU factorization of matrix.
3110    Call this routine before calling `MatLUFactorNumeric()` and after `MatGetFactor()`.
3111 
3112    Collective
3113 
3114    Input Parameters:
3115 +  fact - the factor matrix obtained with `MatGetFactor()`
3116 .  mat - the matrix
3117 .  row - the row permutation
3118 .  col - the column permutation
3119 -  info - options for factorization, includes
3120 .vb
3121           fill - expected fill as ratio of original fill. Run with the option -info to determine an optimal value to use
3122           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3123 .ve
3124 
3125    Level: developer
3126 
3127    Notes:
3128     See [Matrix Factorization](sec_matfactor) for additional information about factorizations
3129 
3130    Most users should employ the simplified `KSP` interface for linear solvers
3131    instead of working directly with matrix algebra routines such as this.
3132    See, e.g., `KSPCreate()`.
3133 
3134    Developer Note:
3135    The Fortran interface is not autogenerated as the
3136    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3137 
3138 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3139 @*/
3140 PetscErrorCode MatLUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
3141 {
3142   MatFactorInfo tinfo;
3143 
3144   PetscFunctionBegin;
3145   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3146   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3147   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
3148   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
3149   if (info) PetscValidPointer(info, 5);
3150   PetscValidType(fact, 1);
3151   PetscValidType(mat, 2);
3152   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3153   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3154   MatCheckPreallocated(mat, 2);
3155   if (!info) {
3156     PetscCall(MatFactorInfoInitialize(&tinfo));
3157     info = &tinfo;
3158   }
3159 
3160   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorSymbolic, mat, row, col, 0));
3161   PetscUseTypeMethod(fact, lufactorsymbolic, mat, row, col, info);
3162   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorSymbolic, mat, row, col, 0));
3163   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3164   PetscFunctionReturn(PETSC_SUCCESS);
3165 }
3166 
3167 /*@C
3168    MatLUFactorNumeric - Performs numeric LU factorization of a matrix.
3169    Call this routine after first calling `MatLUFactorSymbolic()` and `MatGetFactor()`.
3170 
3171    Collective
3172 
3173    Input Parameters:
3174 +  fact - the factor matrix obtained with `MatGetFactor()`
3175 .  mat - the matrix
3176 -  info - options for factorization
3177 
3178    Level: developer
3179 
3180    Notes:
3181    See `MatLUFactor()` for in-place factorization.  See
3182    `MatCholeskyFactorNumeric()` for the symmetric, positive definite case.
3183 
3184    Most users should employ the `KSP` interface for linear solvers
3185    instead of working directly with matrix algebra routines such as this.
3186    See, e.g., `KSPCreate()`.
3187 
3188     Developer Note:
3189     The Fortran interface is not autogenerated as the
3190     interface definition cannot be generated correctly [due to `MatFactorInfo`]
3191 
3192 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactorSymbolic()`, `MatLUFactor()`, `MatCholeskyFactor()`
3193 @*/
3194 PetscErrorCode MatLUFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3195 {
3196   MatFactorInfo tinfo;
3197 
3198   PetscFunctionBegin;
3199   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3200   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3201   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3202   PetscValidType(fact, 1);
3203   PetscValidType(mat, 2);
3204   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3205   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,
3206              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3207 
3208   MatCheckPreallocated(mat, 2);
3209   if (!info) {
3210     PetscCall(MatFactorInfoInitialize(&tinfo));
3211     info = &tinfo;
3212   }
3213 
3214   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_LUFactorNumeric, mat, fact, 0, 0));
3215   else PetscCall(PetscLogEventBegin(MAT_LUFactor, mat, fact, 0, 0));
3216   PetscUseTypeMethod(fact, lufactornumeric, mat, info);
3217   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_LUFactorNumeric, mat, fact, 0, 0));
3218   else PetscCall(PetscLogEventEnd(MAT_LUFactor, mat, fact, 0, 0));
3219   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3220   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3221   PetscFunctionReturn(PETSC_SUCCESS);
3222 }
3223 
3224 /*@C
3225    MatCholeskyFactor - Performs in-place Cholesky factorization of a
3226    symmetric matrix.
3227 
3228    Collective
3229 
3230    Input Parameters:
3231 +  mat - the matrix
3232 .  perm - row and column permutations
3233 -  f - expected fill as ratio of original fill
3234 
3235    Level: developer
3236 
3237    Notes:
3238    See `MatLUFactor()` for the nonsymmetric case.  See also `MatGetFactor()`,
3239    `MatCholeskyFactorSymbolic()`, and `MatCholeskyFactorNumeric()`.
3240 
3241    Most users should employ the `KSP` interface for linear solvers
3242    instead of working directly with matrix algebra routines such as this.
3243    See, e.g., `KSPCreate()`.
3244 
3245    Developer Note:
3246    The Fortran interface is not autogenerated as the
3247    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3248 
3249 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatLUFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactorNumeric()`
3250           `MatGetOrdering()`
3251 @*/
3252 PetscErrorCode MatCholeskyFactor(Mat mat, IS perm, const MatFactorInfo *info)
3253 {
3254   MatFactorInfo tinfo;
3255 
3256   PetscFunctionBegin;
3257   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3258   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 2);
3259   if (info) PetscValidPointer(info, 3);
3260   PetscValidType(mat, 1);
3261   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3262   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3263   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3264   MatCheckPreallocated(mat, 1);
3265   if (!info) {
3266     PetscCall(MatFactorInfoInitialize(&tinfo));
3267     info = &tinfo;
3268   }
3269 
3270   PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, perm, 0, 0));
3271   PetscUseTypeMethod(mat, choleskyfactor, perm, info);
3272   PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, perm, 0, 0));
3273   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3274   PetscFunctionReturn(PETSC_SUCCESS);
3275 }
3276 
3277 /*@C
3278    MatCholeskyFactorSymbolic - Performs symbolic Cholesky factorization
3279    of a symmetric matrix.
3280 
3281    Collective
3282 
3283    Input Parameters:
3284 +  fact - the factor matrix obtained with `MatGetFactor()`
3285 .  mat - the matrix
3286 .  perm - row and column permutations
3287 -  info - options for factorization, includes
3288 .vb
3289           fill - expected fill as ratio of original fill.
3290           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3291                    Run with the option -info to determine an optimal value to use
3292 .ve
3293 
3294    Level: developer
3295 
3296    Notes:
3297    See `MatLUFactorSymbolic()` for the nonsymmetric case.  See also
3298    `MatCholeskyFactor()` and `MatCholeskyFactorNumeric()`.
3299 
3300    Most users should employ the `KSP` interface for linear solvers
3301    instead of working directly with matrix algebra routines such as this.
3302    See, e.g., `KSPCreate()`.
3303 
3304    Developer Note:
3305    The Fortran interface is not autogenerated as the
3306    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3307 
3308 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactor()`, `MatCholeskyFactorNumeric()`
3309           `MatGetOrdering()`
3310 @*/
3311 PetscErrorCode MatCholeskyFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
3312 {
3313   MatFactorInfo tinfo;
3314 
3315   PetscFunctionBegin;
3316   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3317   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3318   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
3319   if (info) PetscValidPointer(info, 4);
3320   PetscValidType(fact, 1);
3321   PetscValidType(mat, 2);
3322   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "Matrix must be square");
3323   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3324   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3325   MatCheckPreallocated(mat, 2);
3326   if (!info) {
3327     PetscCall(MatFactorInfoInitialize(&tinfo));
3328     info = &tinfo;
3329   }
3330 
3331   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3332   PetscUseTypeMethod(fact, choleskyfactorsymbolic, mat, perm, info);
3333   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorSymbolic, mat, perm, 0, 0));
3334   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3335   PetscFunctionReturn(PETSC_SUCCESS);
3336 }
3337 
3338 /*@C
3339    MatCholeskyFactorNumeric - Performs numeric Cholesky factorization
3340    of a symmetric matrix. Call this routine after first calling `MatGetFactor()` and
3341    `MatCholeskyFactorSymbolic()`.
3342 
3343    Collective
3344 
3345    Input Parameters:
3346 +  fact - the factor matrix obtained with `MatGetFactor()`, where the factored values are stored
3347 .  mat - the initial matrix that is to be factored
3348 -  info - options for factorization
3349 
3350    Level: developer
3351 
3352    Note:
3353    Most users should employ the `KSP` interface for linear solvers
3354    instead of working directly with matrix algebra routines such as this.
3355    See, e.g., `KSPCreate()`.
3356 
3357    Developer Note:
3358    The Fortran interface is not autogenerated as the
3359    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3360 
3361 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatCholeskyFactorSymbolic()`, `MatCholeskyFactor()`, `MatLUFactorNumeric()`
3362 @*/
3363 PetscErrorCode MatCholeskyFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3364 {
3365   MatFactorInfo tinfo;
3366 
3367   PetscFunctionBegin;
3368   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3369   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3370   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3371   PetscValidType(fact, 1);
3372   PetscValidType(mat, 2);
3373   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3374   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,
3375              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3376   MatCheckPreallocated(mat, 2);
3377   if (!info) {
3378     PetscCall(MatFactorInfoInitialize(&tinfo));
3379     info = &tinfo;
3380   }
3381 
3382   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3383   else PetscCall(PetscLogEventBegin(MAT_CholeskyFactor, mat, fact, 0, 0));
3384   PetscUseTypeMethod(fact, choleskyfactornumeric, mat, info);
3385   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_CholeskyFactorNumeric, mat, fact, 0, 0));
3386   else PetscCall(PetscLogEventEnd(MAT_CholeskyFactor, mat, fact, 0, 0));
3387   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3388   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3389   PetscFunctionReturn(PETSC_SUCCESS);
3390 }
3391 
3392 /*@
3393    MatQRFactor - Performs in-place QR factorization of matrix.
3394 
3395    Collective
3396 
3397    Input Parameters:
3398 +  mat - the matrix
3399 .  col - column permutation
3400 -  info - options for factorization, includes
3401 .vb
3402           fill - expected fill as ratio of original fill.
3403           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3404                    Run with the option -info to determine an optimal value to use
3405 .ve
3406 
3407    Level: developer
3408 
3409    Notes:
3410    Most users should employ the `KSP` interface for linear solvers
3411    instead of working directly with matrix algebra routines such as this.
3412    See, e.g., `KSPCreate()`.
3413 
3414    This changes the state of the matrix to a factored matrix; it cannot be used
3415    for example with `MatSetValues()` unless one first calls `MatSetUnfactored()`.
3416 
3417    Developer Note:
3418    The Fortran interface is not autogenerated as the
3419    interface definition cannot be generated correctly [due to MatFactorInfo]
3420 
3421 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactorSymbolic()`, `MatQRFactorNumeric()`, `MatLUFactor()`,
3422           `MatSetUnfactored()`, `MatFactorInfo`, `MatGetFactor()`
3423 @*/
3424 PetscErrorCode MatQRFactor(Mat mat, IS col, const MatFactorInfo *info)
3425 {
3426   PetscFunctionBegin;
3427   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3428   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 2);
3429   if (info) PetscValidPointer(info, 3);
3430   PetscValidType(mat, 1);
3431   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3432   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3433   MatCheckPreallocated(mat, 1);
3434   PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, col, 0, 0));
3435   PetscUseMethod(mat, "MatQRFactor_C", (Mat, IS, const MatFactorInfo *), (mat, col, info));
3436   PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, col, 0, 0));
3437   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
3438   PetscFunctionReturn(PETSC_SUCCESS);
3439 }
3440 
3441 /*@
3442    MatQRFactorSymbolic - Performs symbolic QR factorization of matrix.
3443    Call this routine after `MatGetFactor()` but before calling `MatQRFactorNumeric()`.
3444 
3445    Collective
3446 
3447    Input Parameters:
3448 +  fact - the factor matrix obtained with `MatGetFactor()`
3449 .  mat - the matrix
3450 .  col - column permutation
3451 -  info - options for factorization, includes
3452 .vb
3453           fill - expected fill as ratio of original fill.
3454           dtcol - pivot tolerance (0 no pivot, 1 full column pivoting)
3455                    Run with the option -info to determine an optimal value to use
3456 .ve
3457 
3458    Level: developer
3459 
3460    Note:
3461    Most users should employ the `KSP` interface for linear solvers
3462    instead of working directly with matrix algebra routines such as this.
3463    See, e.g., `KSPCreate()`.
3464 
3465    Developer Note:
3466    The Fortran interface is not autogenerated as the
3467    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3468 
3469 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatFactorInfo`, `MatQRFactor()`, `MatQRFactorNumeric()`, `MatLUFactor()`, `MatFactorInfo`, `MatFactorInfoInitialize()`
3470 @*/
3471 PetscErrorCode MatQRFactorSymbolic(Mat fact, Mat mat, IS col, const MatFactorInfo *info)
3472 {
3473   MatFactorInfo tinfo;
3474 
3475   PetscFunctionBegin;
3476   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3477   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3478   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 3);
3479   if (info) PetscValidPointer(info, 4);
3480   PetscValidType(fact, 1);
3481   PetscValidType(mat, 2);
3482   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3483   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
3484   MatCheckPreallocated(mat, 2);
3485   if (!info) {
3486     PetscCall(MatFactorInfoInitialize(&tinfo));
3487     info = &tinfo;
3488   }
3489 
3490   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorSymbolic, fact, mat, col, 0));
3491   PetscUseMethod(fact, "MatQRFactorSymbolic_C", (Mat, Mat, IS, const MatFactorInfo *), (fact, mat, col, info));
3492   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorSymbolic, fact, mat, col, 0));
3493   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3494   PetscFunctionReturn(PETSC_SUCCESS);
3495 }
3496 
3497 /*@
3498    MatQRFactorNumeric - Performs numeric QR factorization of a matrix.
3499    Call this routine after first calling `MatGetFactor()`, and `MatQRFactorSymbolic()`.
3500 
3501    Collective
3502 
3503    Input Parameters:
3504 +  fact - the factor matrix obtained with `MatGetFactor()`
3505 .  mat - the matrix
3506 -  info - options for factorization
3507 
3508    Level: developer
3509 
3510    Notes:
3511    See `MatQRFactor()` for in-place factorization.
3512 
3513    Most users should employ the `KSP` interface for linear solvers
3514    instead of working directly with matrix algebra routines such as this.
3515    See, e.g., `KSPCreate()`.
3516 
3517    Developer Note:
3518    The Fortran interface is not autogenerated as the
3519    interface definition cannot be generated correctly [due to `MatFactorInfo`]
3520 
3521 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorInfo`, `MatGetFactor()`, `MatQRFactor()`, `MatQRFactorSymbolic()`, `MatLUFactor()`
3522 @*/
3523 PetscErrorCode MatQRFactorNumeric(Mat fact, Mat mat, const MatFactorInfo *info)
3524 {
3525   MatFactorInfo tinfo;
3526 
3527   PetscFunctionBegin;
3528   PetscValidHeaderSpecific(fact, MAT_CLASSID, 1);
3529   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
3530   PetscValidType(fact, 1);
3531   PetscValidType(mat, 2);
3532   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
3533   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,
3534              mat->rmap->N, (fact)->rmap->N, mat->cmap->N, (fact)->cmap->N);
3535 
3536   MatCheckPreallocated(mat, 2);
3537   if (!info) {
3538     PetscCall(MatFactorInfoInitialize(&tinfo));
3539     info = &tinfo;
3540   }
3541 
3542   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_QRFactorNumeric, mat, fact, 0, 0));
3543   else PetscCall(PetscLogEventBegin(MAT_QRFactor, mat, fact, 0, 0));
3544   PetscUseMethod(fact, "MatQRFactorNumeric_C", (Mat, Mat, const MatFactorInfo *), (fact, mat, info));
3545   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_QRFactorNumeric, mat, fact, 0, 0));
3546   else PetscCall(PetscLogEventEnd(MAT_QRFactor, mat, fact, 0, 0));
3547   PetscCall(MatViewFromOptions(fact, NULL, "-mat_factor_view"));
3548   PetscCall(PetscObjectStateIncrease((PetscObject)fact));
3549   PetscFunctionReturn(PETSC_SUCCESS);
3550 }
3551 
3552 /*@
3553    MatSolve - Solves A x = b, given a factored matrix.
3554 
3555    Neighbor-wise Collective
3556 
3557    Input Parameters:
3558 +  mat - the factored matrix
3559 -  b - the right-hand-side vector
3560 
3561    Output Parameter:
3562 .  x - the result vector
3563 
3564    Level: developer
3565 
3566    Notes:
3567    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3568    call `MatSolve`(A,x,x).
3569 
3570    Most users should employ the `KSP` interface for linear solvers
3571    instead of working directly with matrix algebra routines such as this.
3572    See, e.g., `KSPCreate()`.
3573 
3574 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactor()`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3575 @*/
3576 PetscErrorCode MatSolve(Mat mat, Vec b, Vec x)
3577 {
3578   PetscFunctionBegin;
3579   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3580   PetscValidType(mat, 1);
3581   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3582   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3583   PetscCheckSameComm(mat, 1, b, 2);
3584   PetscCheckSameComm(mat, 1, x, 3);
3585   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3586   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);
3587   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);
3588   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);
3589   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3590   MatCheckPreallocated(mat, 1);
3591 
3592   PetscCall(PetscLogEventBegin(MAT_Solve, mat, b, x, 0));
3593   if (mat->factorerrortype) {
3594     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3595     PetscCall(VecSetInf(x));
3596   } else PetscUseTypeMethod(mat, solve, b, x);
3597   PetscCall(PetscLogEventEnd(MAT_Solve, mat, b, x, 0));
3598   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3599   PetscFunctionReturn(PETSC_SUCCESS);
3600 }
3601 
3602 static PetscErrorCode MatMatSolve_Basic(Mat A, Mat B, Mat X, PetscBool trans)
3603 {
3604   Vec      b, x;
3605   PetscInt N, i;
3606   PetscErrorCode (*f)(Mat, Vec, Vec);
3607   PetscBool Abound, Bneedconv = PETSC_FALSE, Xneedconv = PETSC_FALSE;
3608 
3609   PetscFunctionBegin;
3610   if (A->factorerrortype) {
3611     PetscCall(PetscInfo(A, "MatFactorError %d\n", A->factorerrortype));
3612     PetscCall(MatSetInf(X));
3613     PetscFunctionReturn(PETSC_SUCCESS);
3614   }
3615   f = (!trans || (!A->ops->solvetranspose && A->symmetric)) ? A->ops->solve : A->ops->solvetranspose;
3616   PetscCheck(f, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Mat type %s", ((PetscObject)A)->type_name);
3617   PetscCall(MatBoundToCPU(A, &Abound));
3618   if (!Abound) {
3619     PetscCall(PetscObjectTypeCompareAny((PetscObject)B, &Bneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3620     PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &Xneedconv, MATSEQDENSE, MATMPIDENSE, ""));
3621   }
3622 #if PetscDefined(HAVE_CUDA)
3623   if (Bneedconv) PetscCall(MatConvert(B, MATDENSECUDA, MAT_INPLACE_MATRIX, &B));
3624   if (Xneedconv) PetscCall(MatConvert(X, MATDENSECUDA, MAT_INPLACE_MATRIX, &X));
3625 #elif PetscDefined(HAVE_HIP)
3626   if (Bneedconv) PetscCall(MatConvert(B, MATDENSEHIP, MAT_INPLACE_MATRIX, &B));
3627   if (Xneedconv) PetscCall(MatConvert(X, MATDENSEHIP, MAT_INPLACE_MATRIX, &X));
3628 #endif
3629   PetscCall(MatGetSize(B, NULL, &N));
3630   for (i = 0; i < N; i++) {
3631     PetscCall(MatDenseGetColumnVecRead(B, i, &b));
3632     PetscCall(MatDenseGetColumnVecWrite(X, i, &x));
3633     PetscCall((*f)(A, b, x));
3634     PetscCall(MatDenseRestoreColumnVecWrite(X, i, &x));
3635     PetscCall(MatDenseRestoreColumnVecRead(B, i, &b));
3636   }
3637   if (Bneedconv) PetscCall(MatConvert(B, MATDENSE, MAT_INPLACE_MATRIX, &B));
3638   if (Xneedconv) PetscCall(MatConvert(X, MATDENSE, MAT_INPLACE_MATRIX, &X));
3639   PetscFunctionReturn(PETSC_SUCCESS);
3640 }
3641 
3642 /*@
3643    MatMatSolve - Solves A X = B, given a factored matrix.
3644 
3645    Neighbor-wise Collective
3646 
3647    Input Parameters:
3648 +  A - the factored matrix
3649 -  B - the right-hand-side matrix `MATDENSE` (or sparse `MATAIJ`-- when using MUMPS)
3650 
3651    Output Parameter:
3652 .  X - the result matrix (dense matrix)
3653 
3654    Level: developer
3655 
3656    Note:
3657    If `B` is a `MATDENSE` matrix then one can call `MatMatSolve`(A,B,B) except with `MATSOLVERMKL_CPARDISO`;
3658    otherwise, `B` and `X` cannot be the same.
3659 
3660 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3661 @*/
3662 PetscErrorCode MatMatSolve(Mat A, Mat B, Mat X)
3663 {
3664   PetscFunctionBegin;
3665   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3666   PetscValidType(A, 1);
3667   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3668   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3669   PetscCheckSameComm(A, 1, B, 2);
3670   PetscCheckSameComm(A, 1, X, 3);
3671   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);
3672   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);
3673   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");
3674   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3675   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3676   MatCheckPreallocated(A, 1);
3677 
3678   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3679   if (!A->ops->matsolve) {
3680     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolve\n", ((PetscObject)A)->type_name));
3681     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_FALSE));
3682   } else PetscUseTypeMethod(A, matsolve, B, X);
3683   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3684   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3685   PetscFunctionReturn(PETSC_SUCCESS);
3686 }
3687 
3688 /*@
3689    MatMatSolveTranspose - Solves A^T X = B, given a factored matrix.
3690 
3691    Neighbor-wise Collective
3692 
3693    Input Parameters:
3694 +  A - the factored matrix
3695 -  B - the right-hand-side matrix  (`MATDENSE` matrix)
3696 
3697    Output Parameter:
3698 .  X - the result matrix (dense matrix)
3699 
3700    Level: developer
3701 
3702    Note:
3703    The matrices `B` and `X` cannot be the same.  I.e., one cannot
3704    call `MatMatSolveTranspose`(A,X,X).
3705 
3706 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolveTranspose()`, `MatMatSolve()`, `MatLUFactor()`, `MatCholeskyFactor()`
3707 @*/
3708 PetscErrorCode MatMatSolveTranspose(Mat A, Mat B, Mat X)
3709 {
3710   PetscFunctionBegin;
3711   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3712   PetscValidType(A, 1);
3713   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
3714   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3715   PetscCheckSameComm(A, 1, B, 2);
3716   PetscCheckSameComm(A, 1, X, 3);
3717   PetscCheck(X != B, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3718   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);
3719   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);
3720   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);
3721   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");
3722   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3723   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3724   MatCheckPreallocated(A, 1);
3725 
3726   PetscCall(PetscLogEventBegin(MAT_MatSolve, A, B, X, 0));
3727   if (!A->ops->matsolvetranspose) {
3728     PetscCall(PetscInfo(A, "Mat type %s using basic MatMatSolveTranspose\n", ((PetscObject)A)->type_name));
3729     PetscCall(MatMatSolve_Basic(A, B, X, PETSC_TRUE));
3730   } else PetscUseTypeMethod(A, matsolvetranspose, B, X);
3731   PetscCall(PetscLogEventEnd(MAT_MatSolve, A, B, X, 0));
3732   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3733   PetscFunctionReturn(PETSC_SUCCESS);
3734 }
3735 
3736 /*@
3737    MatMatTransposeSolve - Solves A X = B^T, given a factored matrix.
3738 
3739    Neighbor-wise Collective
3740 
3741    Input Parameters:
3742 +  A - the factored matrix
3743 -  Bt - the transpose of right-hand-side matrix as a `MATDENSE`
3744 
3745    Output Parameter:
3746 .  X - the result matrix (dense matrix)
3747 
3748    Level: developer
3749 
3750    Note:
3751    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
3752    format on the host processor and call `MatMatTransposeSolve()` to implement MUMPS' `MatMatSolve()`.
3753 
3754 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatMatSolve()`, `MatMatSolveTranspose()`, `MatLUFactor()`, `MatCholeskyFactor()`
3755 @*/
3756 PetscErrorCode MatMatTransposeSolve(Mat A, Mat Bt, Mat X)
3757 {
3758   PetscFunctionBegin;
3759   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
3760   PetscValidType(A, 1);
3761   PetscValidHeaderSpecific(Bt, MAT_CLASSID, 2);
3762   PetscValidHeaderSpecific(X, MAT_CLASSID, 3);
3763   PetscCheckSameComm(A, 1, Bt, 2);
3764   PetscCheckSameComm(A, 1, X, 3);
3765 
3766   PetscCheck(X != Bt, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_IDN, "X and B must be different matrices");
3767   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);
3768   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);
3769   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");
3770   if (!A->rmap->N && !A->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3771   PetscCheck(A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
3772   MatCheckPreallocated(A, 1);
3773 
3774   PetscCall(PetscLogEventBegin(MAT_MatTrSolve, A, Bt, X, 0));
3775   PetscUseTypeMethod(A, mattransposesolve, Bt, X);
3776   PetscCall(PetscLogEventEnd(MAT_MatTrSolve, A, Bt, X, 0));
3777   PetscCall(PetscObjectStateIncrease((PetscObject)X));
3778   PetscFunctionReturn(PETSC_SUCCESS);
3779 }
3780 
3781 /*@
3782    MatForwardSolve - Solves L x = b, given a factored matrix, A = LU, or
3783                             U^T*D^(1/2) x = b, given a factored symmetric matrix, A = U^T*D*U,
3784 
3785    Neighbor-wise Collective
3786 
3787    Input Parameters:
3788 +  mat - the factored matrix
3789 -  b - the right-hand-side vector
3790 
3791    Output Parameter:
3792 .  x - the result vector
3793 
3794    Level: developer
3795 
3796    Notes:
3797    `MatSolve()` should be used for most applications, as it performs
3798    a forward solve followed by a backward solve.
3799 
3800    The vectors `b` and `x` cannot be the same,  i.e., one cannot
3801    call `MatForwardSolve`(A,x,x).
3802 
3803    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3804    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3805    `MatForwardSolve()` solves U^T*D y = b, and
3806    `MatBackwardSolve()` solves U x = y.
3807    Thus they do not provide a symmetric preconditioner.
3808 
3809 .seealso: [](chapter_matrices), `Mat`, `MatBackwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatBackwardSolve()`
3810 @*/
3811 PetscErrorCode MatForwardSolve(Mat mat, Vec b, Vec x)
3812 {
3813   PetscFunctionBegin;
3814   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3815   PetscValidType(mat, 1);
3816   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3817   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3818   PetscCheckSameComm(mat, 1, b, 2);
3819   PetscCheckSameComm(mat, 1, x, 3);
3820   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3821   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);
3822   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);
3823   PetscCheck(mat->rmap->n == b->map->n, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Mat mat,Vec b: local dim %" PetscInt_FMT " %" PetscInt_FMT, mat->rmap->n, b->map->n);
3824   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3825   MatCheckPreallocated(mat, 1);
3826 
3827   PetscCall(PetscLogEventBegin(MAT_ForwardSolve, mat, b, x, 0));
3828   PetscUseTypeMethod(mat, forwardsolve, b, x);
3829   PetscCall(PetscLogEventEnd(MAT_ForwardSolve, mat, b, x, 0));
3830   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3831   PetscFunctionReturn(PETSC_SUCCESS);
3832 }
3833 
3834 /*@
3835    MatBackwardSolve - Solves U x = b, given a factored matrix, A = LU.
3836                              D^(1/2) U x = b, given a factored symmetric matrix, A = U^T*D*U,
3837 
3838    Neighbor-wise Collective
3839 
3840    Input Parameters:
3841 +  mat - the factored matrix
3842 -  b - the right-hand-side vector
3843 
3844    Output Parameter:
3845 .  x - the result vector
3846 
3847    Level: developer
3848 
3849    Notes:
3850    `MatSolve()` should be used for most applications, as it performs
3851    a forward solve followed by a backward solve.
3852 
3853    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3854    call `MatBackwardSolve`(A,x,x).
3855 
3856    For matrix in `MATSEQBAIJ` format with block size larger than 1,
3857    the diagonal blocks are not implemented as D = D^(1/2) * D^(1/2) yet.
3858    `MatForwardSolve()` solves U^T*D y = b, and
3859    `MatBackwardSolve()` solves U x = y.
3860    Thus they do not provide a symmetric preconditioner.
3861 
3862 .seealso: [](chapter_matrices), `Mat`, `MatForwardSolve()`, `MatGetFactor()`, `MatSolve()`, `MatForwardSolve()`
3863 @*/
3864 PetscErrorCode MatBackwardSolve(Mat mat, Vec b, Vec x)
3865 {
3866   PetscFunctionBegin;
3867   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3868   PetscValidType(mat, 1);
3869   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3870   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3871   PetscCheckSameComm(mat, 1, b, 2);
3872   PetscCheckSameComm(mat, 1, x, 3);
3873   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3874   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);
3875   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);
3876   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);
3877   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3878   MatCheckPreallocated(mat, 1);
3879 
3880   PetscCall(PetscLogEventBegin(MAT_BackwardSolve, mat, b, x, 0));
3881   PetscUseTypeMethod(mat, backwardsolve, b, x);
3882   PetscCall(PetscLogEventEnd(MAT_BackwardSolve, mat, b, x, 0));
3883   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3884   PetscFunctionReturn(PETSC_SUCCESS);
3885 }
3886 
3887 /*@
3888    MatSolveAdd - Computes x = y + inv(A)*b, given a factored matrix.
3889 
3890    Neighbor-wise Collective
3891 
3892    Input Parameters:
3893 +  mat - the factored matrix
3894 .  b - the right-hand-side vector
3895 -  y - the vector to be added to
3896 
3897    Output Parameter:
3898 .  x - the result vector
3899 
3900    Level: developer
3901 
3902    Note:
3903    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3904    call `MatSolveAdd`(A,x,y,x).
3905 
3906 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolve()`, `MatGetFactor()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`
3907 @*/
3908 PetscErrorCode MatSolveAdd(Mat mat, Vec b, Vec y, Vec x)
3909 {
3910   PetscScalar one = 1.0;
3911   Vec         tmp;
3912 
3913   PetscFunctionBegin;
3914   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3915   PetscValidType(mat, 1);
3916   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
3917   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3918   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
3919   PetscCheckSameComm(mat, 1, b, 2);
3920   PetscCheckSameComm(mat, 1, y, 3);
3921   PetscCheckSameComm(mat, 1, x, 4);
3922   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3923   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);
3924   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);
3925   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);
3926   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);
3927   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);
3928   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3929   MatCheckPreallocated(mat, 1);
3930 
3931   PetscCall(PetscLogEventBegin(MAT_SolveAdd, mat, b, x, y));
3932   if (mat->factorerrortype) {
3933     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3934     PetscCall(VecSetInf(x));
3935   } else if (mat->ops->solveadd) {
3936     PetscUseTypeMethod(mat, solveadd, b, y, x);
3937   } else {
3938     /* do the solve then the add manually */
3939     if (x != y) {
3940       PetscCall(MatSolve(mat, b, x));
3941       PetscCall(VecAXPY(x, one, y));
3942     } else {
3943       PetscCall(VecDuplicate(x, &tmp));
3944       PetscCall(VecCopy(x, tmp));
3945       PetscCall(MatSolve(mat, b, x));
3946       PetscCall(VecAXPY(x, one, tmp));
3947       PetscCall(VecDestroy(&tmp));
3948     }
3949   }
3950   PetscCall(PetscLogEventEnd(MAT_SolveAdd, mat, b, x, y));
3951   PetscCall(PetscObjectStateIncrease((PetscObject)x));
3952   PetscFunctionReturn(PETSC_SUCCESS);
3953 }
3954 
3955 /*@
3956    MatSolveTranspose - Solves A' x = b, given a factored matrix.
3957 
3958    Neighbor-wise Collective
3959 
3960    Input Parameters:
3961 +  mat - the factored matrix
3962 -  b - the right-hand-side vector
3963 
3964    Output Parameter:
3965 .  x - the result vector
3966 
3967    Level: developer
3968 
3969    Notes:
3970    The vectors `b` and `x` cannot be the same.  I.e., one cannot
3971    call `MatSolveTranspose`(A,x,x).
3972 
3973    Most users should employ the `KSP` interface for linear solvers
3974    instead of working directly with matrix algebra routines such as this.
3975    See, e.g., `KSPCreate()`.
3976 
3977 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `KSP`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTransposeAdd()`
3978 @*/
3979 PetscErrorCode MatSolveTranspose(Mat mat, Vec b, Vec x)
3980 {
3981   PetscErrorCode (*f)(Mat, Vec, Vec) = (!mat->ops->solvetranspose && mat->symmetric) ? mat->ops->solve : mat->ops->solvetranspose;
3982 
3983   PetscFunctionBegin;
3984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
3985   PetscValidType(mat, 1);
3986   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
3987   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
3988   PetscCheckSameComm(mat, 1, b, 2);
3989   PetscCheckSameComm(mat, 1, x, 3);
3990   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
3991   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);
3992   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);
3993   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
3994   MatCheckPreallocated(mat, 1);
3995   PetscCall(PetscLogEventBegin(MAT_SolveTranspose, mat, b, x, 0));
3996   if (mat->factorerrortype) {
3997     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
3998     PetscCall(VecSetInf(x));
3999   } else {
4000     PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Matrix type %s", ((PetscObject)mat)->type_name);
4001     PetscCall((*f)(mat, b, x));
4002   }
4003   PetscCall(PetscLogEventEnd(MAT_SolveTranspose, mat, b, x, 0));
4004   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4005   PetscFunctionReturn(PETSC_SUCCESS);
4006 }
4007 
4008 /*@
4009    MatSolveTransposeAdd - Computes x = y + inv(Transpose(A)) b, given a
4010                       factored matrix.
4011 
4012    Neighbor-wise Collective
4013 
4014    Input Parameters:
4015 +  mat - the factored matrix
4016 .  b - the right-hand-side vector
4017 -  y - the vector to be added to
4018 
4019    Output Parameter:
4020 .  x - the result vector
4021 
4022    Level: developer
4023 
4024    Note:
4025    The vectors `b` and `x` cannot be the same.  I.e., one cannot
4026    call `MatSolveTransposeAdd`(A,x,y,x).
4027 
4028 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatSolve()`, `MatSolveAdd()`, `MatSolveTranspose()`
4029 @*/
4030 PetscErrorCode MatSolveTransposeAdd(Mat mat, Vec b, Vec y, Vec x)
4031 {
4032   PetscScalar one = 1.0;
4033   Vec         tmp;
4034   PetscErrorCode (*f)(Mat, Vec, Vec, Vec) = (!mat->ops->solvetransposeadd && mat->symmetric) ? mat->ops->solveadd : mat->ops->solvetransposeadd;
4035 
4036   PetscFunctionBegin;
4037   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4038   PetscValidType(mat, 1);
4039   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
4040   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4041   PetscValidHeaderSpecific(x, VEC_CLASSID, 4);
4042   PetscCheckSameComm(mat, 1, b, 2);
4043   PetscCheckSameComm(mat, 1, y, 3);
4044   PetscCheckSameComm(mat, 1, x, 4);
4045   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
4046   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);
4047   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);
4048   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);
4049   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);
4050   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
4051   MatCheckPreallocated(mat, 1);
4052 
4053   PetscCall(PetscLogEventBegin(MAT_SolveTransposeAdd, mat, b, x, y));
4054   if (mat->factorerrortype) {
4055     PetscCall(PetscInfo(mat, "MatFactorError %d\n", mat->factorerrortype));
4056     PetscCall(VecSetInf(x));
4057   } else if (f) {
4058     PetscCall((*f)(mat, b, y, x));
4059   } else {
4060     /* do the solve then the add manually */
4061     if (x != y) {
4062       PetscCall(MatSolveTranspose(mat, b, x));
4063       PetscCall(VecAXPY(x, one, y));
4064     } else {
4065       PetscCall(VecDuplicate(x, &tmp));
4066       PetscCall(VecCopy(x, tmp));
4067       PetscCall(MatSolveTranspose(mat, b, x));
4068       PetscCall(VecAXPY(x, one, tmp));
4069       PetscCall(VecDestroy(&tmp));
4070     }
4071   }
4072   PetscCall(PetscLogEventEnd(MAT_SolveTransposeAdd, mat, b, x, y));
4073   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4074   PetscFunctionReturn(PETSC_SUCCESS);
4075 }
4076 
4077 /*@
4078    MatSOR - Computes relaxation (SOR, Gauss-Seidel) sweeps.
4079 
4080    Neighbor-wise Collective
4081 
4082    Input Parameters:
4083 +  mat - the matrix
4084 .  b - the right hand side
4085 .  omega - the relaxation factor
4086 .  flag - flag indicating the type of SOR (see below)
4087 .  shift -  diagonal shift
4088 .  its - the number of iterations
4089 -  lits - the number of local iterations
4090 
4091    Output Parameter:
4092 .  x - the solution (can contain an initial guess, use option `SOR_ZERO_INITIAL_GUESS` to indicate no guess)
4093 
4094    SOR Flags:
4095 +     `SOR_FORWARD_SWEEP` - forward SOR
4096 .     `SOR_BACKWARD_SWEEP` - backward SOR
4097 .     `SOR_SYMMETRIC_SWEEP` - SSOR (symmetric SOR)
4098 .     `SOR_LOCAL_FORWARD_SWEEP` - local forward SOR
4099 .     `SOR_LOCAL_BACKWARD_SWEEP` - local forward SOR
4100 .     `SOR_LOCAL_SYMMETRIC_SWEEP` - local SSOR
4101 .     `SOR_EISENSTAT` - SOR with Eisenstat trick
4102 .     `SOR_APPLY_UPPER`, `SOR_APPLY_LOWER` - applies
4103          upper/lower triangular part of matrix to
4104          vector (with omega)
4105 -     `SOR_ZERO_INITIAL_GUESS` - zero initial guess
4106 
4107    Level: developer
4108 
4109    Notes:
4110    `SOR_LOCAL_FORWARD_SWEEP`, `SOR_LOCAL_BACKWARD_SWEEP`, and
4111    `SOR_LOCAL_SYMMETRIC_SWEEP` perform separate independent smoothings
4112    on each processor.
4113 
4114    Application programmers will not generally use `MatSOR()` directly,
4115    but instead will employ the `KSP`/`PC` interface.
4116 
4117    For `MATBAIJ`, `MATSBAIJ`, and `MATAIJ` matrices with Inodes this does a block SOR smoothing, otherwise it does a pointwise smoothing
4118 
4119    Most users should employ the `KSP` interface for linear solvers
4120    instead of working directly with matrix algebra routines such as this.
4121    See, e.g., `KSPCreate()`.
4122 
4123    Vectors `x` and `b` CANNOT be the same
4124 
4125    The flags are implemented as bitwise inclusive or operations.
4126    For example, use (`SOR_ZERO_INITIAL_GUESS` | `SOR_SYMMETRIC_SWEEP`)
4127    to specify a zero initial guess for SSOR.
4128 
4129    Developer Note:
4130    We should add block SOR support for `MATAIJ` matrices with block size set to great than one and no inodes
4131 
4132 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `KSP`, `PC`, `MatGetFactor()`
4133 @*/
4134 PetscErrorCode MatSOR(Mat mat, Vec b, PetscReal omega, MatSORType flag, PetscReal shift, PetscInt its, PetscInt lits, Vec x)
4135 {
4136   PetscFunctionBegin;
4137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4138   PetscValidType(mat, 1);
4139   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
4140   PetscValidHeaderSpecific(x, VEC_CLASSID, 8);
4141   PetscCheckSameComm(mat, 1, b, 2);
4142   PetscCheckSameComm(mat, 1, x, 8);
4143   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4144   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4145   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);
4146   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);
4147   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);
4148   PetscCheck(its > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires global its %" PetscInt_FMT " positive", its);
4149   PetscCheck(lits > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Relaxation requires local its %" PetscInt_FMT " positive", lits);
4150   PetscCheck(b != x, PETSC_COMM_SELF, PETSC_ERR_ARG_IDN, "b and x vector cannot be the same");
4151 
4152   MatCheckPreallocated(mat, 1);
4153   PetscCall(PetscLogEventBegin(MAT_SOR, mat, b, x, 0));
4154   PetscUseTypeMethod(mat, sor, b, omega, flag, shift, its, lits, x);
4155   PetscCall(PetscLogEventEnd(MAT_SOR, mat, b, x, 0));
4156   PetscCall(PetscObjectStateIncrease((PetscObject)x));
4157   PetscFunctionReturn(PETSC_SUCCESS);
4158 }
4159 
4160 /*
4161       Default matrix copy routine.
4162 */
4163 PetscErrorCode MatCopy_Basic(Mat A, Mat B, MatStructure str)
4164 {
4165   PetscInt           i, rstart = 0, rend = 0, nz;
4166   const PetscInt    *cwork;
4167   const PetscScalar *vwork;
4168 
4169   PetscFunctionBegin;
4170   if (B->assembled) PetscCall(MatZeroEntries(B));
4171   if (str == SAME_NONZERO_PATTERN) {
4172     PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
4173     for (i = rstart; i < rend; i++) {
4174       PetscCall(MatGetRow(A, i, &nz, &cwork, &vwork));
4175       PetscCall(MatSetValues(B, 1, &i, nz, cwork, vwork, INSERT_VALUES));
4176       PetscCall(MatRestoreRow(A, i, &nz, &cwork, &vwork));
4177     }
4178   } else {
4179     PetscCall(MatAYPX(B, 0.0, A, str));
4180   }
4181   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
4182   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
4183   PetscFunctionReturn(PETSC_SUCCESS);
4184 }
4185 
4186 /*@
4187    MatCopy - Copies a matrix to another matrix.
4188 
4189    Collective
4190 
4191    Input Parameters:
4192 +  A - the matrix
4193 -  str - `SAME_NONZERO_PATTERN` or `DIFFERENT_NONZERO_PATTERN`
4194 
4195    Output Parameter:
4196 .  B - where the copy is put
4197 
4198    Level: intermediate
4199 
4200    Notes:
4201    If you use `SAME_NONZERO_PATTERN` then the two matrices must have the same nonzero pattern or the routine will crash.
4202 
4203    `MatCopy()` copies the matrix entries of a matrix to another existing
4204    matrix (after first zeroing the second matrix).  A related routine is
4205    `MatConvert()`, which first creates a new matrix and then copies the data.
4206 
4207 .seealso: [](chapter_matrices), `Mat`, `MatConvert()`, `MatDuplicate()`
4208 @*/
4209 PetscErrorCode MatCopy(Mat A, Mat B, MatStructure str)
4210 {
4211   PetscInt i;
4212 
4213   PetscFunctionBegin;
4214   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
4215   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
4216   PetscValidType(A, 1);
4217   PetscValidType(B, 2);
4218   PetscCheckSameComm(A, 1, B, 2);
4219   MatCheckPreallocated(B, 2);
4220   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4221   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4222   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,
4223              A->cmap->N, B->cmap->N);
4224   MatCheckPreallocated(A, 1);
4225   if (A == B) PetscFunctionReturn(PETSC_SUCCESS);
4226 
4227   PetscCall(PetscLogEventBegin(MAT_Copy, A, B, 0, 0));
4228   if (A->ops->copy) PetscUseTypeMethod(A, copy, B, str);
4229   else PetscCall(MatCopy_Basic(A, B, str));
4230 
4231   B->stencil.dim = A->stencil.dim;
4232   B->stencil.noc = A->stencil.noc;
4233   for (i = 0; i <= A->stencil.dim; i++) {
4234     B->stencil.dims[i]   = A->stencil.dims[i];
4235     B->stencil.starts[i] = A->stencil.starts[i];
4236   }
4237 
4238   PetscCall(PetscLogEventEnd(MAT_Copy, A, B, 0, 0));
4239   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4240   PetscFunctionReturn(PETSC_SUCCESS);
4241 }
4242 
4243 /*@C
4244    MatConvert - Converts a matrix to another matrix, either of the same
4245    or different type.
4246 
4247    Collective
4248 
4249    Input Parameters:
4250 +  mat - the matrix
4251 .  newtype - new matrix type.  Use `MATSAME` to create a new matrix of the
4252    same type as the original matrix.
4253 -  reuse - denotes if the destination matrix is to be created or reused.
4254    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
4255    `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).
4256 
4257    Output Parameter:
4258 .  M - pointer to place new matrix
4259 
4260    Level: intermediate
4261 
4262    Notes:
4263    `MatConvert()` first creates a new matrix and then copies the data from
4264    the first matrix.  A related routine is `MatCopy()`, which copies the matrix
4265    entries of one matrix to another already existing matrix context.
4266 
4267    Cannot be used to convert a sequential matrix to parallel or parallel to sequential,
4268    the MPI communicator of the generated matrix is always the same as the communicator
4269    of the input matrix.
4270 
4271 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatDuplicate()`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
4272 @*/
4273 PetscErrorCode MatConvert(Mat mat, MatType newtype, MatReuse reuse, Mat *M)
4274 {
4275   PetscBool  sametype, issame, flg;
4276   PetscBool3 issymmetric, ishermitian;
4277   char       convname[256], mtype[256];
4278   Mat        B;
4279 
4280   PetscFunctionBegin;
4281   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4282   PetscValidType(mat, 1);
4283   PetscValidPointer(M, 4);
4284   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4285   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4286   MatCheckPreallocated(mat, 1);
4287 
4288   PetscCall(PetscOptionsGetString(((PetscObject)mat)->options, ((PetscObject)mat)->prefix, "-matconvert_type", mtype, sizeof(mtype), &flg));
4289   if (flg) newtype = mtype;
4290 
4291   PetscCall(PetscObjectTypeCompare((PetscObject)mat, newtype, &sametype));
4292   PetscCall(PetscStrcmp(newtype, "same", &issame));
4293   PetscCheck(!(reuse == MAT_INPLACE_MATRIX) || !(mat != *M), PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires same input and output matrix");
4294   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");
4295 
4296   if ((reuse == MAT_INPLACE_MATRIX) && (issame || sametype)) {
4297     PetscCall(PetscInfo(mat, "Early return for inplace %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4298     PetscFunctionReturn(PETSC_SUCCESS);
4299   }
4300 
4301   /* Cache Mat options because some converters use MatHeaderReplace  */
4302   issymmetric = mat->symmetric;
4303   ishermitian = mat->hermitian;
4304 
4305   if ((sametype || issame) && (reuse == MAT_INITIAL_MATRIX) && mat->ops->duplicate) {
4306     PetscCall(PetscInfo(mat, "Calling duplicate for initial matrix %s %d %d\n", ((PetscObject)mat)->type_name, sametype, issame));
4307     PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4308   } else {
4309     PetscErrorCode (*conv)(Mat, MatType, MatReuse, Mat *) = NULL;
4310     const char *prefix[3]                                 = {"seq", "mpi", ""};
4311     PetscInt    i;
4312     /*
4313        Order of precedence:
4314        0) See if newtype is a superclass of the current matrix.
4315        1) See if a specialized converter is known to the current matrix.
4316        2) See if a specialized converter is known to the desired matrix class.
4317        3) See if a good general converter is registered for the desired class
4318           (as of 6/27/03 only MATMPIADJ falls into this category).
4319        4) See if a good general converter is known for the current matrix.
4320        5) Use a really basic converter.
4321     */
4322 
4323     /* 0) See if newtype is a superclass of the current matrix.
4324           i.e mat is mpiaij and newtype is aij */
4325     for (i = 0; i < 2; i++) {
4326       PetscCall(PetscStrncpy(convname, prefix[i], sizeof(convname)));
4327       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4328       PetscCall(PetscStrcmp(convname, ((PetscObject)mat)->type_name, &flg));
4329       PetscCall(PetscInfo(mat, "Check superclass %s %s -> %d\n", convname, ((PetscObject)mat)->type_name, flg));
4330       if (flg) {
4331         if (reuse == MAT_INPLACE_MATRIX) {
4332           PetscCall(PetscInfo(mat, "Early return\n"));
4333           PetscFunctionReturn(PETSC_SUCCESS);
4334         } else if (reuse == MAT_INITIAL_MATRIX && mat->ops->duplicate) {
4335           PetscCall(PetscInfo(mat, "Calling MatDuplicate\n"));
4336           PetscUseTypeMethod(mat, duplicate, MAT_COPY_VALUES, M);
4337           PetscFunctionReturn(PETSC_SUCCESS);
4338         } else if (reuse == MAT_REUSE_MATRIX && mat->ops->copy) {
4339           PetscCall(PetscInfo(mat, "Calling MatCopy\n"));
4340           PetscCall(MatCopy(mat, *M, SAME_NONZERO_PATTERN));
4341           PetscFunctionReturn(PETSC_SUCCESS);
4342         }
4343       }
4344     }
4345     /* 1) See if a specialized converter is known to the current matrix and the desired class */
4346     for (i = 0; i < 3; i++) {
4347       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4348       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4349       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4350       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4351       PetscCall(PetscStrlcat(convname, issame ? ((PetscObject)mat)->type_name : newtype, sizeof(convname)));
4352       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4353       PetscCall(PetscObjectQueryFunction((PetscObject)mat, convname, &conv));
4354       PetscCall(PetscInfo(mat, "Check specialized (1) %s (%s) -> %d\n", convname, ((PetscObject)mat)->type_name, !!conv));
4355       if (conv) goto foundconv;
4356     }
4357 
4358     /* 2)  See if a specialized converter is known to the desired matrix class. */
4359     PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &B));
4360     PetscCall(MatSetSizes(B, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
4361     PetscCall(MatSetType(B, newtype));
4362     for (i = 0; i < 3; i++) {
4363       PetscCall(PetscStrncpy(convname, "MatConvert_", sizeof(convname)));
4364       PetscCall(PetscStrlcat(convname, ((PetscObject)mat)->type_name, sizeof(convname)));
4365       PetscCall(PetscStrlcat(convname, "_", sizeof(convname)));
4366       PetscCall(PetscStrlcat(convname, prefix[i], sizeof(convname)));
4367       PetscCall(PetscStrlcat(convname, newtype, sizeof(convname)));
4368       PetscCall(PetscStrlcat(convname, "_C", sizeof(convname)));
4369       PetscCall(PetscObjectQueryFunction((PetscObject)B, convname, &conv));
4370       PetscCall(PetscInfo(mat, "Check specialized (2) %s (%s) -> %d\n", convname, ((PetscObject)B)->type_name, !!conv));
4371       if (conv) {
4372         PetscCall(MatDestroy(&B));
4373         goto foundconv;
4374       }
4375     }
4376 
4377     /* 3) See if a good general converter is registered for the desired class */
4378     conv = B->ops->convertfrom;
4379     PetscCall(PetscInfo(mat, "Check convertfrom (%s) -> %d\n", ((PetscObject)B)->type_name, !!conv));
4380     PetscCall(MatDestroy(&B));
4381     if (conv) goto foundconv;
4382 
4383     /* 4) See if a good general converter is known for the current matrix */
4384     if (mat->ops->convert) conv = mat->ops->convert;
4385     PetscCall(PetscInfo(mat, "Check general convert (%s) -> %d\n", ((PetscObject)mat)->type_name, !!conv));
4386     if (conv) goto foundconv;
4387 
4388     /* 5) Use a really basic converter. */
4389     PetscCall(PetscInfo(mat, "Using MatConvert_Basic\n"));
4390     conv = MatConvert_Basic;
4391 
4392   foundconv:
4393     PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4394     PetscCall((*conv)(mat, newtype, reuse, M));
4395     if (mat->rmap->mapping && mat->cmap->mapping && !(*M)->rmap->mapping && !(*M)->cmap->mapping) {
4396       /* the block sizes must be same if the mappings are copied over */
4397       (*M)->rmap->bs = mat->rmap->bs;
4398       (*M)->cmap->bs = mat->cmap->bs;
4399       PetscCall(PetscObjectReference((PetscObject)mat->rmap->mapping));
4400       PetscCall(PetscObjectReference((PetscObject)mat->cmap->mapping));
4401       (*M)->rmap->mapping = mat->rmap->mapping;
4402       (*M)->cmap->mapping = mat->cmap->mapping;
4403     }
4404     (*M)->stencil.dim = mat->stencil.dim;
4405     (*M)->stencil.noc = mat->stencil.noc;
4406     for (i = 0; i <= mat->stencil.dim; i++) {
4407       (*M)->stencil.dims[i]   = mat->stencil.dims[i];
4408       (*M)->stencil.starts[i] = mat->stencil.starts[i];
4409     }
4410     PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4411   }
4412   PetscCall(PetscObjectStateIncrease((PetscObject)*M));
4413 
4414   /* Copy Mat options */
4415   if (issymmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_TRUE));
4416   else if (issymmetric == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_SYMMETRIC, PETSC_FALSE));
4417   if (ishermitian == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_TRUE));
4418   else if (ishermitian == PETSC_BOOL3_FALSE) PetscCall(MatSetOption(*M, MAT_HERMITIAN, PETSC_FALSE));
4419   PetscFunctionReturn(PETSC_SUCCESS);
4420 }
4421 
4422 /*@C
4423    MatFactorGetSolverType - Returns name of the package providing the factorization routines
4424 
4425    Not Collective
4426 
4427    Input Parameter:
4428 .  mat - the matrix, must be a factored matrix
4429 
4430    Output Parameter:
4431 .   type - the string name of the package (do not free this string)
4432 
4433    Level: intermediate
4434 
4435    Fortran Note:
4436    Pass in an empty string and the package name will be copied into it. Make sure the string is long enough.
4437 
4438 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatSolverType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4439 @*/
4440 PetscErrorCode MatFactorGetSolverType(Mat mat, MatSolverType *type)
4441 {
4442   PetscErrorCode (*conv)(Mat, MatSolverType *);
4443 
4444   PetscFunctionBegin;
4445   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4446   PetscValidType(mat, 1);
4447   PetscValidPointer(type, 2);
4448   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
4449   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorGetSolverType_C", &conv));
4450   if (conv) PetscCall((*conv)(mat, type));
4451   else *type = MATSOLVERPETSC;
4452   PetscFunctionReturn(PETSC_SUCCESS);
4453 }
4454 
4455 typedef struct _MatSolverTypeForSpecifcType *MatSolverTypeForSpecifcType;
4456 struct _MatSolverTypeForSpecifcType {
4457   MatType mtype;
4458   /* no entry for MAT_FACTOR_NONE */
4459   PetscErrorCode (*createfactor[MAT_FACTOR_NUM_TYPES - 1])(Mat, MatFactorType, Mat *);
4460   MatSolverTypeForSpecifcType next;
4461 };
4462 
4463 typedef struct _MatSolverTypeHolder *MatSolverTypeHolder;
4464 struct _MatSolverTypeHolder {
4465   char                       *name;
4466   MatSolverTypeForSpecifcType handlers;
4467   MatSolverTypeHolder         next;
4468 };
4469 
4470 static MatSolverTypeHolder MatSolverTypeHolders = NULL;
4471 
4472 /*@C
4473    MatSolverTypeRegister - Registers a `MatSolverType` that works for a particular matrix type
4474 
4475    Input Parameters:
4476 +    package - name of the package, for example petsc or superlu
4477 .    mtype - the matrix type that works with this package
4478 .    ftype - the type of factorization supported by the package
4479 -    createfactor - routine that will create the factored matrix ready to be used
4480 
4481     Level: developer
4482 
4483 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorGetSolverType()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`
4484 @*/
4485 PetscErrorCode MatSolverTypeRegister(MatSolverType package, MatType mtype, MatFactorType ftype, PetscErrorCode (*createfactor)(Mat, MatFactorType, Mat *))
4486 {
4487   MatSolverTypeHolder         next = MatSolverTypeHolders, prev = NULL;
4488   PetscBool                   flg;
4489   MatSolverTypeForSpecifcType inext, iprev = NULL;
4490 
4491   PetscFunctionBegin;
4492   PetscCall(MatInitializePackage());
4493   if (!next) {
4494     PetscCall(PetscNew(&MatSolverTypeHolders));
4495     PetscCall(PetscStrallocpy(package, &MatSolverTypeHolders->name));
4496     PetscCall(PetscNew(&MatSolverTypeHolders->handlers));
4497     PetscCall(PetscStrallocpy(mtype, (char **)&MatSolverTypeHolders->handlers->mtype));
4498     MatSolverTypeHolders->handlers->createfactor[(int)ftype - 1] = createfactor;
4499     PetscFunctionReturn(PETSC_SUCCESS);
4500   }
4501   while (next) {
4502     PetscCall(PetscStrcasecmp(package, next->name, &flg));
4503     if (flg) {
4504       PetscCheck(next->handlers, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatSolverTypeHolder is missing handlers");
4505       inext = next->handlers;
4506       while (inext) {
4507         PetscCall(PetscStrcasecmp(mtype, inext->mtype, &flg));
4508         if (flg) {
4509           inext->createfactor[(int)ftype - 1] = createfactor;
4510           PetscFunctionReturn(PETSC_SUCCESS);
4511         }
4512         iprev = inext;
4513         inext = inext->next;
4514       }
4515       PetscCall(PetscNew(&iprev->next));
4516       PetscCall(PetscStrallocpy(mtype, (char **)&iprev->next->mtype));
4517       iprev->next->createfactor[(int)ftype - 1] = createfactor;
4518       PetscFunctionReturn(PETSC_SUCCESS);
4519     }
4520     prev = next;
4521     next = next->next;
4522   }
4523   PetscCall(PetscNew(&prev->next));
4524   PetscCall(PetscStrallocpy(package, &prev->next->name));
4525   PetscCall(PetscNew(&prev->next->handlers));
4526   PetscCall(PetscStrallocpy(mtype, (char **)&prev->next->handlers->mtype));
4527   prev->next->handlers->createfactor[(int)ftype - 1] = createfactor;
4528   PetscFunctionReturn(PETSC_SUCCESS);
4529 }
4530 
4531 /*@C
4532    MatSolverTypeGet - Gets the function that creates the factor matrix if it exist
4533 
4534    Input Parameters:
4535 +    type - name of the package, for example petsc or superlu
4536 .    ftype - the type of factorization supported by the type
4537 -    mtype - the matrix type that works with this type
4538 
4539    Output Parameters:
4540 +   foundtype - `PETSC_TRUE` if the type was registered
4541 .   foundmtype - `PETSC_TRUE` if the type supports the requested mtype
4542 -   createfactor - routine that will create the factored matrix ready to be used or `NULL` if not found
4543 
4544     Level: developer
4545 
4546 .seealso: [](chapter_matrices), `Mat`, `MatFactorType`, `MatType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatSolverTypeRegister()`, `MatGetFactor()`
4547 @*/
4548 PetscErrorCode MatSolverTypeGet(MatSolverType type, MatType mtype, MatFactorType ftype, PetscBool *foundtype, PetscBool *foundmtype, PetscErrorCode (**createfactor)(Mat, MatFactorType, Mat *))
4549 {
4550   MatSolverTypeHolder         next = MatSolverTypeHolders;
4551   PetscBool                   flg;
4552   MatSolverTypeForSpecifcType inext;
4553 
4554   PetscFunctionBegin;
4555   if (foundtype) *foundtype = PETSC_FALSE;
4556   if (foundmtype) *foundmtype = PETSC_FALSE;
4557   if (createfactor) *createfactor = NULL;
4558 
4559   if (type) {
4560     while (next) {
4561       PetscCall(PetscStrcasecmp(type, next->name, &flg));
4562       if (flg) {
4563         if (foundtype) *foundtype = PETSC_TRUE;
4564         inext = next->handlers;
4565         while (inext) {
4566           PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4567           if (flg) {
4568             if (foundmtype) *foundmtype = PETSC_TRUE;
4569             if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4570             PetscFunctionReturn(PETSC_SUCCESS);
4571           }
4572           inext = inext->next;
4573         }
4574       }
4575       next = next->next;
4576     }
4577   } else {
4578     while (next) {
4579       inext = next->handlers;
4580       while (inext) {
4581         PetscCall(PetscStrcmp(mtype, inext->mtype, &flg));
4582         if (flg && inext->createfactor[(int)ftype - 1]) {
4583           if (foundtype) *foundtype = PETSC_TRUE;
4584           if (foundmtype) *foundmtype = PETSC_TRUE;
4585           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4586           PetscFunctionReturn(PETSC_SUCCESS);
4587         }
4588         inext = inext->next;
4589       }
4590       next = next->next;
4591     }
4592     /* try with base classes inext->mtype */
4593     next = MatSolverTypeHolders;
4594     while (next) {
4595       inext = next->handlers;
4596       while (inext) {
4597         PetscCall(PetscStrbeginswith(mtype, inext->mtype, &flg));
4598         if (flg && inext->createfactor[(int)ftype - 1]) {
4599           if (foundtype) *foundtype = PETSC_TRUE;
4600           if (foundmtype) *foundmtype = PETSC_TRUE;
4601           if (createfactor) *createfactor = inext->createfactor[(int)ftype - 1];
4602           PetscFunctionReturn(PETSC_SUCCESS);
4603         }
4604         inext = inext->next;
4605       }
4606       next = next->next;
4607     }
4608   }
4609   PetscFunctionReturn(PETSC_SUCCESS);
4610 }
4611 
4612 PetscErrorCode MatSolverTypeDestroy(void)
4613 {
4614   MatSolverTypeHolder         next = MatSolverTypeHolders, prev;
4615   MatSolverTypeForSpecifcType inext, iprev;
4616 
4617   PetscFunctionBegin;
4618   while (next) {
4619     PetscCall(PetscFree(next->name));
4620     inext = next->handlers;
4621     while (inext) {
4622       PetscCall(PetscFree(inext->mtype));
4623       iprev = inext;
4624       inext = inext->next;
4625       PetscCall(PetscFree(iprev));
4626     }
4627     prev = next;
4628     next = next->next;
4629     PetscCall(PetscFree(prev));
4630   }
4631   MatSolverTypeHolders = NULL;
4632   PetscFunctionReturn(PETSC_SUCCESS);
4633 }
4634 
4635 /*@C
4636    MatFactorGetCanUseOrdering - Indicates if the factorization can use the ordering provided in `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4637 
4638    Logically Collective
4639 
4640    Input Parameter:
4641 .  mat - the matrix
4642 
4643    Output Parameter:
4644 .  flg - `PETSC_TRUE` if uses the ordering
4645 
4646    Level: developer
4647 
4648    Note:
4649    Most internal PETSc factorizations use the ordering passed to the factorization routine but external
4650    packages do not, thus we want to skip generating the ordering when it is not needed or used.
4651 
4652 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4653 @*/
4654 PetscErrorCode MatFactorGetCanUseOrdering(Mat mat, PetscBool *flg)
4655 {
4656   PetscFunctionBegin;
4657   *flg = mat->canuseordering;
4658   PetscFunctionReturn(PETSC_SUCCESS);
4659 }
4660 
4661 /*@C
4662    MatFactorGetPreferredOrdering - The preferred ordering for a particular matrix factor object
4663 
4664    Logically Collective
4665 
4666    Input Parameters:
4667 +  mat - the matrix obtained with `MatGetFactor()`
4668 -  ftype - the factorization type to be used
4669 
4670    Output Parameter:
4671 .  otype - the preferred ordering type
4672 
4673    Level: developer
4674 
4675 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatFactorType`, `MatOrderingType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatCholeskyFactorSymbolic()`
4676 @*/
4677 PetscErrorCode MatFactorGetPreferredOrdering(Mat mat, MatFactorType ftype, MatOrderingType *otype)
4678 {
4679   PetscFunctionBegin;
4680   *otype = mat->preferredordering[ftype];
4681   PetscCheck(*otype, PETSC_COMM_SELF, PETSC_ERR_PLIB, "MatFactor did not have a preferred ordering");
4682   PetscFunctionReturn(PETSC_SUCCESS);
4683 }
4684 
4685 /*@C
4686    MatGetFactor - Returns a matrix suitable to calls to MatXXFactorSymbolic()
4687 
4688    Collective
4689 
4690    Input Parameters:
4691 +  mat - the matrix
4692 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4693 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4694 
4695    Output Parameter:
4696 .  f - the factor matrix used with MatXXFactorSymbolic() calls. Can be `NULL` in some cases, see notes below.
4697 
4698    Options Database Key:
4699 .  -mat_factor_bind_factorization <host, device> - Where to do matrix factorization? Default is device (might consume more device memory.
4700                                   One can choose host to save device memory). Currently only supported with `MATSEQAIJCUSPARSE` matrices.
4701 
4702    Level: intermediate
4703 
4704    Notes:
4705      The return matrix can be `NULL` if the requested factorization is not available, since some combinations of matrix types and factorization
4706      types registered with `MatSolverTypeRegister()` cannot be fully tested if not at runtime.
4707 
4708      Users usually access the factorization solvers via `KSP`
4709 
4710       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4711      such as pastix, superlu, mumps etc.
4712 
4713       PETSc must have been ./configure to use the external solver, using the option --download-package
4714 
4715       Some of the packages have options for controlling the factorization, these are in the form -prefix_mat_packagename_packageoption
4716       where prefix is normally obtained from the calling `KSP`/`PC`. If `MatGetFactor()` is called directly one can set
4717       call `MatSetOptionsPrefixFactor()` on the originating matrix or  `MatSetOptionsPrefix()` on the resulting factor matrix.
4718 
4719    Developer Note:
4720       This should actually be called `MatCreateFactor()` since it creates a new factor object
4721 
4722 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `KSP`, `MatSolverType`, `MatFactorType`, `MatCopy()`, `MatDuplicate()`, `MatGetFactorAvailable()`, `MatFactorGetCanUseOrdering()`, `MatSolverTypeRegister()`,
4723           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4724 @*/
4725 PetscErrorCode MatGetFactor(Mat mat, MatSolverType type, MatFactorType ftype, Mat *f)
4726 {
4727   PetscBool foundtype, foundmtype;
4728   PetscErrorCode (*conv)(Mat, MatFactorType, Mat *);
4729 
4730   PetscFunctionBegin;
4731   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4732   PetscValidType(mat, 1);
4733 
4734   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4735   MatCheckPreallocated(mat, 1);
4736 
4737   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, &foundtype, &foundmtype, &conv));
4738   if (!foundtype) {
4739     if (type) {
4740       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],
4741               ((PetscObject)mat)->type_name, type);
4742     } else {
4743       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);
4744     }
4745   }
4746   PetscCheck(foundmtype, PetscObjectComm((PetscObject)mat), PETSC_ERR_MISSING_FACTOR, "MatSolverType %s does not support matrix type %s", type, ((PetscObject)mat)->type_name);
4747   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);
4748 
4749   PetscCall((*conv)(mat, ftype, f));
4750   if (mat->factorprefix) PetscCall(MatSetOptionsPrefix(*f, mat->factorprefix));
4751   PetscFunctionReturn(PETSC_SUCCESS);
4752 }
4753 
4754 /*@C
4755    MatGetFactorAvailable - Returns a a flag if matrix supports particular type and factor type
4756 
4757    Not Collective
4758 
4759    Input Parameters:
4760 +  mat - the matrix
4761 .  type - name of solver type, for example, superlu, petsc (to use PETSc's default)
4762 -  ftype - factor type, `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4763 
4764    Output Parameter:
4765 .    flg - PETSC_TRUE if the factorization is available
4766 
4767    Level: intermediate
4768 
4769    Notes:
4770       Some PETSc matrix formats have alternative solvers available that are contained in alternative packages
4771      such as pastix, superlu, mumps etc.
4772 
4773       PETSc must have been ./configure to use the external solver, using the option --download-package
4774 
4775    Developer Note:
4776       This should actually be called MatCreateFactorAvailable() since MatGetFactor() creates a new factor object
4777 
4778 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatSolverType`, `MatFactorType`, `MatGetFactor()`, `MatCopy()`, `MatDuplicate()`, `MatGetFactor()`, `MatSolverTypeRegister()`,
4779           `MAT_FACTOR_LU`, `MAT_FACTOR_CHOLESKY`, `MAT_FACTOR_ICC`, `MAT_FACTOR_ILU`, `MAT_FACTOR_QR`
4780 @*/
4781 PetscErrorCode MatGetFactorAvailable(Mat mat, MatSolverType type, MatFactorType ftype, PetscBool *flg)
4782 {
4783   PetscErrorCode (*gconv)(Mat, MatFactorType, Mat *);
4784 
4785   PetscFunctionBegin;
4786   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4787   PetscValidType(mat, 1);
4788   PetscValidBoolPointer(flg, 4);
4789 
4790   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4791   MatCheckPreallocated(mat, 1);
4792 
4793   PetscCall(MatSolverTypeGet(type, ((PetscObject)mat)->type_name, ftype, NULL, NULL, &gconv));
4794   *flg = gconv ? PETSC_TRUE : PETSC_FALSE;
4795   PetscFunctionReturn(PETSC_SUCCESS);
4796 }
4797 
4798 /*@
4799    MatDuplicate - Duplicates a matrix including the non-zero structure.
4800 
4801    Collective
4802 
4803    Input Parameters:
4804 +  mat - the matrix
4805 -  op - One of `MAT_DO_NOT_COPY_VALUES`, `MAT_COPY_VALUES`, or `MAT_SHARE_NONZERO_PATTERN`.
4806         See the manual page for `MatDuplicateOption()` for an explanation of these options.
4807 
4808    Output Parameter:
4809 .  M - pointer to place new matrix
4810 
4811    Level: intermediate
4812 
4813    Notes:
4814     You cannot change the nonzero pattern for the parent or child matrix if you use `MAT_SHARE_NONZERO_PATTERN`.
4815 
4816     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.
4817 
4818     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
4819     is duplicated and the internal data structures created for the reuse of previous matrix operations are not duplicated.
4820     User should not use `MatDuplicate()` to create new matrix M if M is intended to be reused as the product of matrix operation.
4821 
4822 .seealso: [](chapter_matrices), `Mat`, `MatCopy()`, `MatConvert()`, `MatDuplicateOption`
4823 @*/
4824 PetscErrorCode MatDuplicate(Mat mat, MatDuplicateOption op, Mat *M)
4825 {
4826   Mat         B;
4827   VecType     vtype;
4828   PetscInt    i;
4829   PetscObject dm, container_h, container_d;
4830   void (*viewf)(void);
4831 
4832   PetscFunctionBegin;
4833   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4834   PetscValidType(mat, 1);
4835   PetscValidPointer(M, 3);
4836   PetscCheck(op != MAT_COPY_VALUES || mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "MAT_COPY_VALUES not allowed for unassembled matrix");
4837   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4838   MatCheckPreallocated(mat, 1);
4839 
4840   *M = NULL;
4841   PetscCall(PetscLogEventBegin(MAT_Convert, mat, 0, 0, 0));
4842   PetscUseTypeMethod(mat, duplicate, op, M);
4843   PetscCall(PetscLogEventEnd(MAT_Convert, mat, 0, 0, 0));
4844   B = *M;
4845 
4846   PetscCall(MatGetOperation(mat, MATOP_VIEW, &viewf));
4847   if (viewf) PetscCall(MatSetOperation(B, MATOP_VIEW, viewf));
4848   PetscCall(MatGetVecType(mat, &vtype));
4849   PetscCall(MatSetVecType(B, vtype));
4850 
4851   B->stencil.dim = mat->stencil.dim;
4852   B->stencil.noc = mat->stencil.noc;
4853   for (i = 0; i <= mat->stencil.dim; i++) {
4854     B->stencil.dims[i]   = mat->stencil.dims[i];
4855     B->stencil.starts[i] = mat->stencil.starts[i];
4856   }
4857 
4858   B->nooffproczerorows = mat->nooffproczerorows;
4859   B->nooffprocentries  = mat->nooffprocentries;
4860 
4861   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_dm", &dm));
4862   if (dm) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_dm", dm));
4863   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Host", &container_h));
4864   if (container_h) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Host", container_h));
4865   PetscCall(PetscObjectQuery((PetscObject)mat, "__PETSc_MatCOOStruct_Device", &container_d));
4866   if (container_d) PetscCall(PetscObjectCompose((PetscObject)B, "__PETSc_MatCOOStruct_Device", container_d));
4867   PetscCall(PetscObjectStateIncrease((PetscObject)B));
4868   PetscFunctionReturn(PETSC_SUCCESS);
4869 }
4870 
4871 /*@
4872    MatGetDiagonal - Gets the diagonal of a matrix as a `Vec`
4873 
4874    Logically Collective
4875 
4876    Input Parameter:
4877 .  mat - the matrix
4878 
4879    Output Parameter:
4880 .  v - the diagonal of the matrix
4881 
4882    Level: intermediate
4883 
4884    Note:
4885    Currently only correct in parallel for square matrices.
4886 
4887 .seealso: [](chapter_matrices), `Mat`, `Vec`, `MatGetRow()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`
4888 @*/
4889 PetscErrorCode MatGetDiagonal(Mat mat, Vec v)
4890 {
4891   PetscFunctionBegin;
4892   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4893   PetscValidType(mat, 1);
4894   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4895   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4896   MatCheckPreallocated(mat, 1);
4897 
4898   PetscUseTypeMethod(mat, getdiagonal, v);
4899   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4900   PetscFunctionReturn(PETSC_SUCCESS);
4901 }
4902 
4903 /*@C
4904    MatGetRowMin - Gets the minimum value (of the real part) of each
4905         row of the matrix
4906 
4907    Logically Collective
4908 
4909    Input Parameter:
4910 .  mat - the matrix
4911 
4912    Output Parameters:
4913 +  v - the vector for storing the maximums
4914 -  idx - the indices of the column found for each row (optional)
4915 
4916    Level: intermediate
4917 
4918    Note:
4919     The result of this call are the same as if one converted the matrix to dense format
4920       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
4921 
4922     This code is only implemented for a couple of matrix formats.
4923 
4924 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`,
4925           `MatGetRowMax()`
4926 @*/
4927 PetscErrorCode MatGetRowMin(Mat mat, Vec v, PetscInt idx[])
4928 {
4929   PetscFunctionBegin;
4930   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4931   PetscValidType(mat, 1);
4932   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4933   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4934 
4935   if (!mat->cmap->N) {
4936     PetscCall(VecSet(v, PETSC_MAX_REAL));
4937     if (idx) {
4938       PetscInt i, m = mat->rmap->n;
4939       for (i = 0; i < m; i++) idx[i] = -1;
4940     }
4941   } else {
4942     MatCheckPreallocated(mat, 1);
4943   }
4944   PetscUseTypeMethod(mat, getrowmin, v, idx);
4945   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4946   PetscFunctionReturn(PETSC_SUCCESS);
4947 }
4948 
4949 /*@C
4950    MatGetRowMinAbs - Gets the minimum value (in absolute value) of each
4951         row of the matrix
4952 
4953    Logically Collective
4954 
4955    Input Parameter:
4956 .  mat - the matrix
4957 
4958    Output Parameters:
4959 +  v - the vector for storing the minimums
4960 -  idx - the indices of the column found for each row (or `NULL` if not needed)
4961 
4962    Level: intermediate
4963 
4964    Notes:
4965     if a row is completely empty or has only 0.0 values then the idx[] value for that
4966     row is 0 (the first column).
4967 
4968     This code is only implemented for a couple of matrix formats.
4969 
4970 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`
4971 @*/
4972 PetscErrorCode MatGetRowMinAbs(Mat mat, Vec v, PetscInt idx[])
4973 {
4974   PetscFunctionBegin;
4975   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
4976   PetscValidType(mat, 1);
4977   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
4978   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
4979   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
4980 
4981   if (!mat->cmap->N) {
4982     PetscCall(VecSet(v, 0.0));
4983     if (idx) {
4984       PetscInt i, m = mat->rmap->n;
4985       for (i = 0; i < m; i++) idx[i] = -1;
4986     }
4987   } else {
4988     MatCheckPreallocated(mat, 1);
4989     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
4990     PetscUseTypeMethod(mat, getrowminabs, v, idx);
4991   }
4992   PetscCall(PetscObjectStateIncrease((PetscObject)v));
4993   PetscFunctionReturn(PETSC_SUCCESS);
4994 }
4995 
4996 /*@C
4997    MatGetRowMax - Gets the maximum value (of the real part) of each
4998         row of the matrix
4999 
5000    Logically Collective
5001 
5002    Input Parameter:
5003 .  mat - the matrix
5004 
5005    Output Parameters:
5006 +  v - the vector for storing the maximums
5007 -  idx - the indices of the column found for each row (optional)
5008 
5009    Level: intermediate
5010 
5011    Notes:
5012     The result of this call are the same as if one converted the matrix to dense format
5013       and found the minimum value in each row (i.e. the implicit zeros are counted as zeros).
5014 
5015     This code is only implemented for a couple of matrix formats.
5016 
5017 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMaxAbs()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5018 @*/
5019 PetscErrorCode MatGetRowMax(Mat mat, Vec v, PetscInt idx[])
5020 {
5021   PetscFunctionBegin;
5022   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5023   PetscValidType(mat, 1);
5024   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5025   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5026 
5027   if (!mat->cmap->N) {
5028     PetscCall(VecSet(v, PETSC_MIN_REAL));
5029     if (idx) {
5030       PetscInt i, m = mat->rmap->n;
5031       for (i = 0; i < m; i++) idx[i] = -1;
5032     }
5033   } else {
5034     MatCheckPreallocated(mat, 1);
5035     PetscUseTypeMethod(mat, getrowmax, v, idx);
5036   }
5037   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5038   PetscFunctionReturn(PETSC_SUCCESS);
5039 }
5040 
5041 /*@C
5042    MatGetRowMaxAbs - Gets the maximum value (in absolute value) of each
5043         row of the matrix
5044 
5045    Logically Collective
5046 
5047    Input Parameter:
5048 .  mat - the matrix
5049 
5050    Output Parameters:
5051 +  v - the vector for storing the maximums
5052 -  idx - the indices of the column found for each row (or `NULL` if not needed)
5053 
5054    Level: intermediate
5055 
5056    Notes:
5057     if a row is completely empty or has only 0.0 values then the idx[] value for that
5058     row is 0 (the first column).
5059 
5060     This code is only implemented for a couple of matrix formats.
5061 
5062 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMinAbs()`
5063 @*/
5064 PetscErrorCode MatGetRowMaxAbs(Mat mat, Vec v, PetscInt idx[])
5065 {
5066   PetscFunctionBegin;
5067   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5068   PetscValidType(mat, 1);
5069   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5071 
5072   if (!mat->cmap->N) {
5073     PetscCall(VecSet(v, 0.0));
5074     if (idx) {
5075       PetscInt i, m = mat->rmap->n;
5076       for (i = 0; i < m; i++) idx[i] = -1;
5077     }
5078   } else {
5079     MatCheckPreallocated(mat, 1);
5080     if (idx) PetscCall(PetscArrayzero(idx, mat->rmap->n));
5081     PetscUseTypeMethod(mat, getrowmaxabs, v, idx);
5082   }
5083   PetscCall(PetscObjectStateIncrease((PetscObject)v));
5084   PetscFunctionReturn(PETSC_SUCCESS);
5085 }
5086 
5087 /*@
5088    MatGetRowSum - Gets the sum of each row of the matrix
5089 
5090    Logically or Neighborhood Collective
5091 
5092    Input Parameter:
5093 .  mat - the matrix
5094 
5095    Output Parameter:
5096 .  v - the vector for storing the sum of rows
5097 
5098    Level: intermediate
5099 
5100    Notes:
5101     This code is slow since it is not currently specialized for different formats
5102 
5103 .seealso: [](chapter_matrices), `Mat`, `MatGetDiagonal()`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRowMax()`, `MatGetRowMin()`, `MatGetRowMaxAbs()`, `MatGetRowMinAbs()`
5104 @*/
5105 PetscErrorCode MatGetRowSum(Mat mat, Vec v)
5106 {
5107   Vec ones;
5108 
5109   PetscFunctionBegin;
5110   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5111   PetscValidType(mat, 1);
5112   PetscValidHeaderSpecific(v, VEC_CLASSID, 2);
5113   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5114   MatCheckPreallocated(mat, 1);
5115   PetscCall(MatCreateVecs(mat, &ones, NULL));
5116   PetscCall(VecSet(ones, 1.));
5117   PetscCall(MatMult(mat, ones, v));
5118   PetscCall(VecDestroy(&ones));
5119   PetscFunctionReturn(PETSC_SUCCESS);
5120 }
5121 
5122 /*@
5123    MatTransposeSetPrecursor - Set the matrix from which the second matrix will receive numerical transpose data with a call to `MatTranspose`(A,`MAT_REUSE_MATRIX`,&B)
5124    when B was not obtained with `MatTranspose`(A,`MAT_INITIAL_MATRIX`,&B)
5125 
5126    Collective
5127 
5128    Input Parameter:
5129 .  mat - the matrix to provide the transpose
5130 
5131    Output Parameter:
5132 .  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
5133 
5134    Level: advanced
5135 
5136    Note:
5137    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
5138    routine allows bypassing that call.
5139 
5140 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSymbolic()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5141 @*/
5142 PetscErrorCode MatTransposeSetPrecursor(Mat mat, Mat B)
5143 {
5144   PetscContainer  rB = NULL;
5145   MatParentState *rb = NULL;
5146 
5147   PetscFunctionBegin;
5148   PetscCall(PetscNew(&rb));
5149   rb->id    = ((PetscObject)mat)->id;
5150   rb->state = 0;
5151   PetscCall(MatGetNonzeroState(mat, &rb->nonzerostate));
5152   PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)B), &rB));
5153   PetscCall(PetscContainerSetPointer(rB, rb));
5154   PetscCall(PetscContainerSetUserDestroy(rB, PetscContainerUserDestroyDefault));
5155   PetscCall(PetscObjectCompose((PetscObject)B, "MatTransposeParent", (PetscObject)rB));
5156   PetscCall(PetscObjectDereference((PetscObject)rB));
5157   PetscFunctionReturn(PETSC_SUCCESS);
5158 }
5159 
5160 /*@
5161    MatTranspose - Computes an in-place or out-of-place transpose of a matrix.
5162 
5163    Collective
5164 
5165    Input Parameters:
5166 +  mat - the matrix to transpose
5167 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5168 
5169    Output Parameter:
5170 .  B - the transpose
5171 
5172    Level: intermediate
5173 
5174    Notes:
5175      If you use `MAT_INPLACE_MATRIX` then you must pass in &mat for B
5176 
5177      `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
5178      transpose, call `MatTransposeSetPrecursor`(mat,B) before calling this routine.
5179 
5180      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.
5181 
5182      Consider using `MatCreateTranspose()` instead if you only need a matrix that behaves like the transpose, but don't need the storage to be changed.
5183 
5184      If mat is unchanged from the last call this function returns immediately without recomputing the result
5185 
5186      If you only need the symbolic transpose, and not the numerical values, use `MatTransposeSymbolic()`
5187 
5188 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`,
5189           `MatTransposeSymbolic()`, `MatCreateTranspose()`
5190 @*/
5191 PetscErrorCode MatTranspose(Mat mat, MatReuse reuse, Mat *B)
5192 {
5193   PetscContainer  rB = NULL;
5194   MatParentState *rb = NULL;
5195 
5196   PetscFunctionBegin;
5197   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5198   PetscValidType(mat, 1);
5199   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5200   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5201   PetscCheck(reuse != MAT_INPLACE_MATRIX || mat == *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "MAT_INPLACE_MATRIX requires last matrix to match first");
5202   PetscCheck(reuse != MAT_REUSE_MATRIX || mat != *B, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Perhaps you mean MAT_INPLACE_MATRIX");
5203   MatCheckPreallocated(mat, 1);
5204   if (reuse == MAT_REUSE_MATRIX) {
5205     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5206     PetscCheck(rB, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose(). Suggest MatTransposeSetPrecursor().");
5207     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5208     PetscCheck(rb->id == ((PetscObject)mat)->id, PetscObjectComm((PetscObject)*B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5209     if (rb->state == ((PetscObject)mat)->state) PetscFunctionReturn(PETSC_SUCCESS);
5210   }
5211 
5212   PetscCall(PetscLogEventBegin(MAT_Transpose, mat, 0, 0, 0));
5213   if (reuse != MAT_INPLACE_MATRIX || mat->symmetric != PETSC_BOOL3_TRUE) {
5214     PetscUseTypeMethod(mat, transpose, reuse, B);
5215     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5216   }
5217   PetscCall(PetscLogEventEnd(MAT_Transpose, mat, 0, 0, 0));
5218 
5219   if (reuse == MAT_INITIAL_MATRIX) PetscCall(MatTransposeSetPrecursor(mat, *B));
5220   if (reuse != MAT_INPLACE_MATRIX) {
5221     PetscCall(PetscObjectQuery((PetscObject)*B, "MatTransposeParent", (PetscObject *)&rB));
5222     PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5223     rb->state        = ((PetscObject)mat)->state;
5224     rb->nonzerostate = mat->nonzerostate;
5225   }
5226   PetscFunctionReturn(PETSC_SUCCESS);
5227 }
5228 
5229 /*@
5230    MatTransposeSymbolic - Computes the symbolic part of the transpose of a matrix.
5231 
5232    Collective
5233 
5234    Input Parameter:
5235 .  A - the matrix to transpose
5236 
5237    Output Parameter:
5238 .  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
5239       numerical portion.
5240 
5241    Level: intermediate
5242 
5243    Note:
5244    This is not supported for many matrix types, use `MatTranspose()` in those cases
5245 
5246 .seealso: [](chapter_matrices), `Mat`, `MatTransposeSetPrecursor()`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`, `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, `MAT_INPLACE_MATRIX`
5247 @*/
5248 PetscErrorCode MatTransposeSymbolic(Mat A, Mat *B)
5249 {
5250   PetscFunctionBegin;
5251   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5252   PetscValidType(A, 1);
5253   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5254   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5255   PetscCall(PetscLogEventBegin(MAT_Transpose, A, 0, 0, 0));
5256   PetscUseTypeMethod(A, transposesymbolic, B);
5257   PetscCall(PetscLogEventEnd(MAT_Transpose, A, 0, 0, 0));
5258 
5259   PetscCall(MatTransposeSetPrecursor(A, *B));
5260   PetscFunctionReturn(PETSC_SUCCESS);
5261 }
5262 
5263 PetscErrorCode MatTransposeCheckNonzeroState_Private(Mat A, Mat B)
5264 {
5265   PetscContainer  rB;
5266   MatParentState *rb;
5267 
5268   PetscFunctionBegin;
5269   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5270   PetscValidType(A, 1);
5271   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5272   PetscCheck(!A->factortype, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5273   PetscCall(PetscObjectQuery((PetscObject)B, "MatTransposeParent", (PetscObject *)&rB));
5274   PetscCheck(rB, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from call to MatTranspose()");
5275   PetscCall(PetscContainerGetPointer(rB, (void **)&rb));
5276   PetscCheck(rb->id == ((PetscObject)A)->id, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONG, "Reuse matrix used was not generated from input matrix");
5277   PetscCheck(rb->nonzerostate == A->nonzerostate, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Reuse matrix has changed nonzero structure");
5278   PetscFunctionReturn(PETSC_SUCCESS);
5279 }
5280 
5281 /*@
5282    MatIsTranspose - Test whether a matrix is another one's transpose,
5283         or its own, in which case it tests symmetry.
5284 
5285    Collective
5286 
5287    Input Parameters:
5288 +  A - the matrix to test
5289 .  B - the matrix to test against, this can equal the first parameter
5290 -  tol - tolerance, differences between entries smaller than this are counted as zero
5291 
5292    Output Parameter:
5293 .  flg - the result
5294 
5295    Level: intermediate
5296 
5297    Notes:
5298    Only available for `MATAIJ` matrices.
5299 
5300    The sequential algorithm has a running time of the order of the number of nonzeros; the parallel
5301    test involves parallel copies of the block-offdiagonal parts of the matrix.
5302 
5303 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`
5304 @*/
5305 PetscErrorCode MatIsTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5306 {
5307   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5308 
5309   PetscFunctionBegin;
5310   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5311   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5312   PetscValidBoolPointer(flg, 4);
5313   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsTranspose_C", &f));
5314   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsTranspose_C", &g));
5315   *flg = PETSC_FALSE;
5316   if (f && g) {
5317     PetscCheck(f == g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for symmetry test");
5318     PetscCall((*f)(A, B, tol, flg));
5319   } else {
5320     MatType mattype;
5321 
5322     PetscCall(MatGetType(f ? B : A, &mattype));
5323     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Matrix of type %s does not support checking for transpose", mattype);
5324   }
5325   PetscFunctionReturn(PETSC_SUCCESS);
5326 }
5327 
5328 /*@
5329    MatHermitianTranspose - Computes an in-place or out-of-place Hermitian transpose of a matrix in complex conjugate.
5330 
5331    Collective
5332 
5333    Input Parameters:
5334 +  mat - the matrix to transpose and complex conjugate
5335 -  reuse - either `MAT_INITIAL_MATRIX`, `MAT_REUSE_MATRIX`, or `MAT_INPLACE_MATRIX`
5336 
5337    Output Parameter:
5338 .  B - the Hermitian transpose
5339 
5340    Level: intermediate
5341 
5342 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatMultTranspose()`, `MatMultTransposeAdd()`, `MatIsTranspose()`, `MatReuse`
5343 @*/
5344 PetscErrorCode MatHermitianTranspose(Mat mat, MatReuse reuse, Mat *B)
5345 {
5346   PetscFunctionBegin;
5347   PetscCall(MatTranspose(mat, reuse, B));
5348 #if defined(PETSC_USE_COMPLEX)
5349   PetscCall(MatConjugate(*B));
5350 #endif
5351   PetscFunctionReturn(PETSC_SUCCESS);
5352 }
5353 
5354 /*@
5355    MatIsHermitianTranspose - Test whether a matrix is another one's Hermitian transpose,
5356 
5357    Collective
5358 
5359    Input Parameters:
5360 +  A - the matrix to test
5361 .  B - the matrix to test against, this can equal the first parameter
5362 -  tol - tolerance, differences between entries smaller than this are counted as zero
5363 
5364    Output Parameter:
5365 .  flg - the result
5366 
5367    Level: intermediate
5368 
5369    Notes:
5370    Only available for `MATAIJ` matrices.
5371 
5372    The sequential algorithm
5373    has a running time of the order of the number of nonzeros; the parallel
5374    test involves parallel copies of the block-offdiagonal parts of the matrix.
5375 
5376 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsTranspose()`
5377 @*/
5378 PetscErrorCode MatIsHermitianTranspose(Mat A, Mat B, PetscReal tol, PetscBool *flg)
5379 {
5380   PetscErrorCode (*f)(Mat, Mat, PetscReal, PetscBool *), (*g)(Mat, Mat, PetscReal, PetscBool *);
5381 
5382   PetscFunctionBegin;
5383   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5384   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5385   PetscValidBoolPointer(flg, 4);
5386   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatIsHermitianTranspose_C", &f));
5387   PetscCall(PetscObjectQueryFunction((PetscObject)B, "MatIsHermitianTranspose_C", &g));
5388   if (f && g) {
5389     PetscCheck(f != g, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_NOTSAMETYPE, "Matrices do not have the same comparator for Hermitian test");
5390     PetscCall((*f)(A, B, tol, flg));
5391   }
5392   PetscFunctionReturn(PETSC_SUCCESS);
5393 }
5394 
5395 /*@
5396    MatPermute - Creates a new matrix with rows and columns permuted from the
5397    original.
5398 
5399    Collective
5400 
5401    Input Parameters:
5402 +  mat - the matrix to permute
5403 .  row - row permutation, each processor supplies only the permutation for its rows
5404 -  col - column permutation, each processor supplies only the permutation for its columns
5405 
5406    Output Parameter:
5407 .  B - the permuted matrix
5408 
5409    Level: advanced
5410 
5411    Note:
5412    The index sets map from row/col of permuted matrix to row/col of original matrix.
5413    The index sets should be on the same communicator as mat and have the same local sizes.
5414 
5415    Developer Note:
5416      If you want to implement `MatPermute()` for a matrix type, and your approach doesn't
5417      exploit the fact that row and col are permutations, consider implementing the
5418      more general `MatCreateSubMatrix()` instead.
5419 
5420 .seealso: [](chapter_matrices), `Mat`, `MatGetOrdering()`, `ISAllGather()`, `MatCreateSubMatrix()`
5421 @*/
5422 PetscErrorCode MatPermute(Mat mat, IS row, IS col, Mat *B)
5423 {
5424   PetscFunctionBegin;
5425   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5426   PetscValidType(mat, 1);
5427   PetscValidHeaderSpecific(row, IS_CLASSID, 2);
5428   PetscValidHeaderSpecific(col, IS_CLASSID, 3);
5429   PetscValidPointer(B, 4);
5430   PetscCheckSameComm(mat, 1, row, 2);
5431   if (row != col) PetscCheckSameComm(row, 2, col, 3);
5432   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5433   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5434   PetscCheck(mat->ops->permute || mat->ops->createsubmatrix, PETSC_COMM_SELF, PETSC_ERR_SUP, "MatPermute not available for Mat type %s", ((PetscObject)mat)->type_name);
5435   MatCheckPreallocated(mat, 1);
5436 
5437   if (mat->ops->permute) {
5438     PetscUseTypeMethod(mat, permute, row, col, B);
5439     PetscCall(PetscObjectStateIncrease((PetscObject)*B));
5440   } else {
5441     PetscCall(MatCreateSubMatrix(mat, row, col, MAT_INITIAL_MATRIX, B));
5442   }
5443   PetscFunctionReturn(PETSC_SUCCESS);
5444 }
5445 
5446 /*@
5447    MatEqual - Compares two matrices.
5448 
5449    Collective
5450 
5451    Input Parameters:
5452 +  A - the first matrix
5453 -  B - the second matrix
5454 
5455    Output Parameter:
5456 .  flg - `PETSC_TRUE` if the matrices are equal; `PETSC_FALSE` otherwise.
5457 
5458    Level: intermediate
5459 
5460 .seealso: [](chapter_matrices), `Mat`
5461 @*/
5462 PetscErrorCode MatEqual(Mat A, Mat B, PetscBool *flg)
5463 {
5464   PetscFunctionBegin;
5465   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
5466   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
5467   PetscValidType(A, 1);
5468   PetscValidType(B, 2);
5469   PetscValidBoolPointer(flg, 3);
5470   PetscCheckSameComm(A, 1, B, 2);
5471   MatCheckPreallocated(A, 1);
5472   MatCheckPreallocated(B, 2);
5473   PetscCheck(A->assembled, PetscObjectComm((PetscObject)A), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5474   PetscCheck(B->assembled, PetscObjectComm((PetscObject)B), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5475   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,
5476              B->cmap->N);
5477   if (A->ops->equal && A->ops->equal == B->ops->equal) {
5478     PetscUseTypeMethod(A, equal, B, flg);
5479   } else {
5480     PetscCall(MatMultEqual(A, B, 10, flg));
5481   }
5482   PetscFunctionReturn(PETSC_SUCCESS);
5483 }
5484 
5485 /*@
5486    MatDiagonalScale - Scales a matrix on the left and right by diagonal
5487    matrices that are stored as vectors.  Either of the two scaling
5488    matrices can be `NULL`.
5489 
5490    Collective
5491 
5492    Input Parameters:
5493 +  mat - the matrix to be scaled
5494 .  l - the left scaling vector (or `NULL`)
5495 -  r - the right scaling vector (or `NULL`)
5496 
5497    Level: intermediate
5498 
5499    Note:
5500    `MatDiagonalScale()` computes A = LAR, where
5501    L = a diagonal matrix (stored as a vector), R = a diagonal matrix (stored as a vector)
5502    The L scales the rows of the matrix, the R scales the columns of the matrix.
5503 
5504 .seealso: [](chapter_matrices), `Mat`, `MatScale()`, `MatShift()`, `MatDiagonalSet()`
5505 @*/
5506 PetscErrorCode MatDiagonalScale(Mat mat, Vec l, Vec r)
5507 {
5508   PetscFunctionBegin;
5509   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5510   PetscValidType(mat, 1);
5511   if (l) {
5512     PetscValidHeaderSpecific(l, VEC_CLASSID, 2);
5513     PetscCheckSameComm(mat, 1, l, 2);
5514   }
5515   if (r) {
5516     PetscValidHeaderSpecific(r, VEC_CLASSID, 3);
5517     PetscCheckSameComm(mat, 1, r, 3);
5518   }
5519   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5520   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5521   MatCheckPreallocated(mat, 1);
5522   if (!l && !r) PetscFunctionReturn(PETSC_SUCCESS);
5523 
5524   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5525   PetscUseTypeMethod(mat, diagonalscale, l, r);
5526   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5527   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5528   if (l != r) mat->symmetric = PETSC_BOOL3_FALSE;
5529   PetscFunctionReturn(PETSC_SUCCESS);
5530 }
5531 
5532 /*@
5533     MatScale - Scales all elements of a matrix by a given number.
5534 
5535     Logically Collective
5536 
5537     Input Parameters:
5538 +   mat - the matrix to be scaled
5539 -   a  - the scaling value
5540 
5541     Level: intermediate
5542 
5543 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
5544 @*/
5545 PetscErrorCode MatScale(Mat mat, PetscScalar a)
5546 {
5547   PetscFunctionBegin;
5548   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5549   PetscValidType(mat, 1);
5550   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5551   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5552   PetscValidLogicalCollectiveScalar(mat, a, 2);
5553   MatCheckPreallocated(mat, 1);
5554 
5555   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
5556   if (a != (PetscScalar)1.0) {
5557     PetscUseTypeMethod(mat, scale, a);
5558     PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5559   }
5560   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
5561   PetscFunctionReturn(PETSC_SUCCESS);
5562 }
5563 
5564 /*@
5565    MatNorm - Calculates various norms of a matrix.
5566 
5567    Collective
5568 
5569    Input Parameters:
5570 +  mat - the matrix
5571 -  type - the type of norm, `NORM_1`, `NORM_FROBENIUS`, `NORM_INFINITY`
5572 
5573    Output Parameter:
5574 .  nrm - the resulting norm
5575 
5576    Level: intermediate
5577 
5578 .seealso: [](chapter_matrices), `Mat`
5579 @*/
5580 PetscErrorCode MatNorm(Mat mat, NormType type, PetscReal *nrm)
5581 {
5582   PetscFunctionBegin;
5583   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5584   PetscValidType(mat, 1);
5585   PetscValidRealPointer(nrm, 3);
5586 
5587   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
5588   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
5589   MatCheckPreallocated(mat, 1);
5590 
5591   PetscUseTypeMethod(mat, norm, type, nrm);
5592   PetscFunctionReturn(PETSC_SUCCESS);
5593 }
5594 
5595 /*
5596      This variable is used to prevent counting of MatAssemblyBegin() that
5597    are called from within a MatAssemblyEnd().
5598 */
5599 static PetscInt MatAssemblyEnd_InUse = 0;
5600 /*@
5601    MatAssemblyBegin - Begins assembling the matrix.  This routine should
5602    be called after completing all calls to `MatSetValues()`.
5603 
5604    Collective
5605 
5606    Input Parameters:
5607 +  mat - the matrix
5608 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5609 
5610    Level: beginner
5611 
5612    Notes:
5613    `MatSetValues()` generally caches the values that belong to other MPI ranks.  The matrix is ready to
5614    use only after `MatAssemblyBegin()` and `MatAssemblyEnd()` have been called.
5615 
5616    Use `MAT_FLUSH_ASSEMBLY` when switching between `ADD_VALUES` and `INSERT_VALUES`
5617    in `MatSetValues()`; use `MAT_FINAL_ASSEMBLY` for the final assembly before
5618    using the matrix.
5619 
5620    ALL processes that share a matrix MUST call `MatAssemblyBegin()` and `MatAssemblyEnd()` the SAME NUMBER of times, and each time with the
5621    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
5622    a global collective operation requiring all processes that share the matrix.
5623 
5624    Space for preallocated nonzeros that is not filled by a call to `MatSetValues()` or a related routine are compressed
5625    out by assembly. If you intend to use that extra space on a subsequent assembly, be sure to insert explicit zeros
5626    before `MAT_FINAL_ASSEMBLY` so the space is not compressed out.
5627 
5628 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssembled()`
5629 @*/
5630 PetscErrorCode MatAssemblyBegin(Mat mat, MatAssemblyType type)
5631 {
5632   PetscFunctionBegin;
5633   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5634   PetscValidType(mat, 1);
5635   MatCheckPreallocated(mat, 1);
5636   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix.\nDid you forget to call MatSetUnfactored()?");
5637   if (mat->assembled) {
5638     mat->was_assembled = PETSC_TRUE;
5639     mat->assembled     = PETSC_FALSE;
5640   }
5641 
5642   if (!MatAssemblyEnd_InUse) {
5643     PetscCall(PetscLogEventBegin(MAT_AssemblyBegin, mat, 0, 0, 0));
5644     PetscTryTypeMethod(mat, assemblybegin, type);
5645     PetscCall(PetscLogEventEnd(MAT_AssemblyBegin, mat, 0, 0, 0));
5646   } else PetscTryTypeMethod(mat, assemblybegin, type);
5647   PetscFunctionReturn(PETSC_SUCCESS);
5648 }
5649 
5650 /*@
5651    MatAssembled - Indicates if a matrix has been assembled and is ready for
5652      use; for example, in matrix-vector product.
5653 
5654    Not Collective
5655 
5656    Input Parameter:
5657 .  mat - the matrix
5658 
5659    Output Parameter:
5660 .  assembled - `PETSC_TRUE` or `PETSC_FALSE`
5661 
5662    Level: advanced
5663 
5664 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyEnd()`, `MatSetValues()`, `MatAssemblyBegin()`
5665 @*/
5666 PetscErrorCode MatAssembled(Mat mat, PetscBool *assembled)
5667 {
5668   PetscFunctionBegin;
5669   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5670   PetscValidBoolPointer(assembled, 2);
5671   *assembled = mat->assembled;
5672   PetscFunctionReturn(PETSC_SUCCESS);
5673 }
5674 
5675 /*@
5676    MatAssemblyEnd - Completes assembling the matrix.  This routine should
5677    be called after `MatAssemblyBegin()`.
5678 
5679    Collective
5680 
5681    Input Parameters:
5682 +  mat - the matrix
5683 -  type - type of assembly, either `MAT_FLUSH_ASSEMBLY` or `MAT_FINAL_ASSEMBLY`
5684 
5685    Options Database Keys:
5686 +  -mat_view ::ascii_info - Prints info on matrix at conclusion of `MatEndAssembly()`
5687 .  -mat_view ::ascii_info_detail - Prints more detailed info
5688 .  -mat_view - Prints matrix in ASCII format
5689 .  -mat_view ::ascii_matlab - Prints matrix in Matlab format
5690 .  -mat_view draw - draws nonzero structure of matrix, using `MatView()` and `PetscDrawOpenX()`.
5691 .  -display <name> - Sets display name (default is host)
5692 .  -draw_pause <sec> - Sets number of seconds to pause after display
5693 .  -mat_view socket - Sends matrix to socket, can be accessed from Matlab (See [Using MATLAB with PETSc](ch_matlab))
5694 .  -viewer_socket_machine <machine> - Machine to use for socket
5695 .  -viewer_socket_port <port> - Port number to use for socket
5696 -  -mat_view binary:filename[:append] - Save matrix to file in binary format
5697 
5698    Level: beginner
5699 
5700 .seealso: [](chapter_matrices), `Mat`, `MatAssemblyBegin()`, `MatSetValues()`, `PetscDrawOpenX()`, `PetscDrawCreate()`, `MatView()`, `MatAssembled()`, `PetscViewerSocketOpen()`
5701 @*/
5702 PetscErrorCode MatAssemblyEnd(Mat mat, MatAssemblyType type)
5703 {
5704   static PetscInt inassm = 0;
5705   PetscBool       flg    = PETSC_FALSE;
5706 
5707   PetscFunctionBegin;
5708   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5709   PetscValidType(mat, 1);
5710 
5711   inassm++;
5712   MatAssemblyEnd_InUse++;
5713   if (MatAssemblyEnd_InUse == 1) { /* Do the logging only the first time through */
5714     PetscCall(PetscLogEventBegin(MAT_AssemblyEnd, mat, 0, 0, 0));
5715     PetscTryTypeMethod(mat, assemblyend, type);
5716     PetscCall(PetscLogEventEnd(MAT_AssemblyEnd, mat, 0, 0, 0));
5717   } else PetscTryTypeMethod(mat, assemblyend, type);
5718 
5719   /* Flush assembly is not a true assembly */
5720   if (type != MAT_FLUSH_ASSEMBLY) {
5721     if (mat->num_ass) {
5722       if (!mat->symmetry_eternal) {
5723         mat->symmetric = PETSC_BOOL3_UNKNOWN;
5724         mat->hermitian = PETSC_BOOL3_UNKNOWN;
5725       }
5726       if (!mat->structural_symmetry_eternal && mat->ass_nonzerostate != mat->nonzerostate) mat->structurally_symmetric = PETSC_BOOL3_UNKNOWN;
5727       if (!mat->spd_eternal) mat->spd = PETSC_BOOL3_UNKNOWN;
5728     }
5729     mat->num_ass++;
5730     mat->assembled        = PETSC_TRUE;
5731     mat->ass_nonzerostate = mat->nonzerostate;
5732   }
5733 
5734   mat->insertmode = NOT_SET_VALUES;
5735   MatAssemblyEnd_InUse--;
5736   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
5737   if (inassm == 1 && type != MAT_FLUSH_ASSEMBLY) {
5738     PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
5739 
5740     if (mat->checksymmetryonassembly) {
5741       PetscCall(MatIsSymmetric(mat, mat->checksymmetrytol, &flg));
5742       if (flg) {
5743         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5744       } else {
5745         PetscCall(PetscPrintf(PetscObjectComm((PetscObject)mat), "Matrix is not symmetric (tolerance %g)\n", (double)mat->checksymmetrytol));
5746       }
5747     }
5748     if (mat->nullsp && mat->checknullspaceonassembly) PetscCall(MatNullSpaceTest(mat->nullsp, mat, NULL));
5749   }
5750   inassm--;
5751   PetscFunctionReturn(PETSC_SUCCESS);
5752 }
5753 
5754 /*@
5755    MatSetOption - Sets a parameter option for a matrix. Some options
5756    may be specific to certain storage formats.  Some options
5757    determine how values will be inserted (or added). Sorted,
5758    row-oriented input will generally assemble the fastest. The default
5759    is row-oriented.
5760 
5761    Logically Collective for certain operations, such as `MAT_SPD`, not collective for `MAT_ROW_ORIENTED`, see `MatOption`
5762 
5763    Input Parameters:
5764 +  mat - the matrix
5765 .  option - the option, one of those listed below (and possibly others),
5766 -  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5767 
5768   Options Describing Matrix Structure:
5769 +    `MAT_SPD` - symmetric positive definite
5770 .    `MAT_SYMMETRIC` - symmetric in terms of both structure and value
5771 .    `MAT_HERMITIAN` - transpose is the complex conjugation
5772 .    `MAT_STRUCTURALLY_SYMMETRIC` - symmetric nonzero structure
5773 .    `MAT_SYMMETRY_ETERNAL` - indicates the symmetry (or Hermitian structure) or its absence will persist through any changes to the matrix
5774 .    `MAT_STRUCTURAL_SYMMETRY_ETERNAL` - indicates the structural symmetry or its absence will persist through any changes to the matrix
5775 -    `MAT_SPD_ETERNAL` - indicates the value of `MAT_SPD` (true or false) will persist through any changes to the matrix
5776 
5777    These are not really options of the matrix, they are knowledge about the structure of the matrix that users may provide so that they
5778    do not need to be computed (usually at a high cost)
5779 
5780    Options For Use with `MatSetValues()`:
5781    Insert a logically dense subblock, which can be
5782 .    `MAT_ROW_ORIENTED` - row-oriented (default)
5783 
5784    These options reflect the data you pass in with `MatSetValues()`; it has
5785    nothing to do with how the data is stored internally in the matrix
5786    data structure.
5787 
5788    When (re)assembling a matrix, we can restrict the input for
5789    efficiency/debugging purposes.  These options include
5790 +    `MAT_NEW_NONZERO_LOCATIONS` - additional insertions will be allowed if they generate a new nonzero (slow)
5791 .    `MAT_FORCE_DIAGONAL_ENTRIES` - forces diagonal entries to be allocated
5792 .    `MAT_IGNORE_OFF_PROC_ENTRIES` - drops off-processor entries
5793 .    `MAT_NEW_NONZERO_LOCATION_ERR` - generates an error for new matrix entry
5794 .    `MAT_USE_HASH_TABLE` - uses a hash table to speed up matrix assembly
5795 .    `MAT_NO_OFF_PROC_ENTRIES` - you know each process will only set values for its own rows, will generate an error if
5796         any process sets values for another process. This avoids all reductions in the MatAssembly routines and thus improves
5797         performance for very large process counts.
5798 -    `MAT_SUBSET_OFF_PROC_ENTRIES` - you know that the first assembly after setting this flag will set a superset
5799         of the off-process entries required for all subsequent assemblies. This avoids a rendezvous step in the MatAssembly
5800         functions, instead sending only neighbor messages.
5801 
5802    Level: intermediate
5803 
5804    Notes:
5805    Except for `MAT_UNUSED_NONZERO_LOCATION_ERR` and  `MAT_ROW_ORIENTED` all processes that share the matrix must pass the same value in flg!
5806 
5807    Some options are relevant only for particular matrix types and
5808    are thus ignored by others.  Other options are not supported by
5809    certain matrix types and will generate an error message if set.
5810 
5811    If using Fortran to compute a matrix, one may need to
5812    use the column-oriented option (or convert to the row-oriented
5813    format).
5814 
5815    `MAT_NEW_NONZERO_LOCATIONS` set to `PETSC_FALSE` indicates that any add or insertion
5816    that would generate a new entry in the nonzero structure is instead
5817    ignored.  Thus, if memory has not already been allocated for this particular
5818    data, then the insertion is ignored. For dense matrices, in which
5819    the entire array is allocated, no entries are ever ignored.
5820    Set after the first `MatAssemblyEnd()`. If this option is set then the MatAssemblyBegin/End() processes has one less global reduction
5821 
5822    `MAT_NEW_NONZERO_LOCATION_ERR` set to PETSC_TRUE indicates that any add or insertion
5823    that would generate a new entry in the nonzero structure instead produces
5824    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
5825 
5826    `MAT_NEW_NONZERO_ALLOCATION_ERR` set to `PETSC_TRUE` indicates that any add or insertion
5827    that would generate a new entry that has not been preallocated will
5828    instead produce an error. (Currently supported for `MATAIJ` and `MATBAIJ` formats
5829    only.) This is a useful flag when debugging matrix memory preallocation.
5830    If this option is set then the `MatAssemblyBegin()`/`MatAssemblyEnd()` processes has one less global reduction
5831 
5832    `MAT_IGNORE_OFF_PROC_ENTRIES` set to `PETSC_TRUE` indicates entries destined for
5833    other processors should be dropped, rather than stashed.
5834    This is useful if you know that the "owning" processor is also
5835    always generating the correct matrix entries, so that PETSc need
5836    not transfer duplicate entries generated on another processor.
5837 
5838    `MAT_USE_HASH_TABLE` indicates that a hash table be used to improve the
5839    searches during matrix assembly. When this flag is set, the hash table
5840    is created during the first matrix assembly. This hash table is
5841    used the next time through, during `MatSetValues()`/`MatSetValuesBlocked()`
5842    to improve the searching of indices. `MAT_NEW_NONZERO_LOCATIONS` flag
5843    should be used with `MAT_USE_HASH_TABLE` flag. This option is currently
5844    supported by `MATMPIBAIJ` format only.
5845 
5846    `MAT_KEEP_NONZERO_PATTERN` indicates when `MatZeroRows()` is called the zeroed entries
5847    are kept in the nonzero structure
5848 
5849    `MAT_IGNORE_ZERO_ENTRIES` - for `MATAIJ` and `MATIS` matrices this will stop zero values from creating
5850    a zero location in the matrix
5851 
5852    `MAT_USE_INODES` - indicates using inode version of the code - works with `MATAIJ` matrix types
5853 
5854    `MAT_NO_OFF_PROC_ZERO_ROWS` - you know each process will only zero its own rows. This avoids all reductions in the
5855         zero row routines and thus improves performance for very large process counts.
5856 
5857    `MAT_IGNORE_LOWER_TRIANGULAR` - For `MATSBAIJ` matrices will ignore any insertions you make in the lower triangular
5858         part of the matrix (since they should match the upper triangular part).
5859 
5860    `MAT_SORTED_FULL` - each process provides exactly its local rows; all column indices for a given row are passed in a
5861                      single call to `MatSetValues()`, preallocation is perfect, row oriented, `INSERT_VALUES` is used. Common
5862                      with finite difference schemes with non-periodic boundary conditions.
5863 
5864    Developer Note:
5865    `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, and `MAT_SPD_ETERNAL` are used by `MatAssemblyEnd()` and in other
5866    places where otherwise the value of `MAT_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRIC` or `MAT_SPD` would need to be changed back
5867    to `PETSC_BOOL3_UNKNOWN` because the matrix values had changed so the code cannot be certain that the related property had
5868    not changed.
5869 
5870 .seealso: [](chapter_matrices), `MatOption`, `Mat`, `MatGetOption()`
5871 @*/
5872 PetscErrorCode MatSetOption(Mat mat, MatOption op, PetscBool flg)
5873 {
5874   PetscFunctionBegin;
5875   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5876   if (op > 0) {
5877     PetscValidLogicalCollectiveEnum(mat, op, 2);
5878     PetscValidLogicalCollectiveBool(mat, flg, 3);
5879   }
5880 
5881   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);
5882 
5883   switch (op) {
5884   case MAT_FORCE_DIAGONAL_ENTRIES:
5885     mat->force_diagonals = flg;
5886     PetscFunctionReturn(PETSC_SUCCESS);
5887   case MAT_NO_OFF_PROC_ENTRIES:
5888     mat->nooffprocentries = flg;
5889     PetscFunctionReturn(PETSC_SUCCESS);
5890   case MAT_SUBSET_OFF_PROC_ENTRIES:
5891     mat->assembly_subset = flg;
5892     if (!mat->assembly_subset) { /* See the same logic in VecAssembly wrt VEC_SUBSET_OFF_PROC_ENTRIES */
5893 #if !defined(PETSC_HAVE_MPIUNI)
5894       PetscCall(MatStashScatterDestroy_BTS(&mat->stash));
5895 #endif
5896       mat->stash.first_assembly_done = PETSC_FALSE;
5897     }
5898     PetscFunctionReturn(PETSC_SUCCESS);
5899   case MAT_NO_OFF_PROC_ZERO_ROWS:
5900     mat->nooffproczerorows = flg;
5901     PetscFunctionReturn(PETSC_SUCCESS);
5902   case MAT_SPD:
5903     if (flg) {
5904       mat->spd                    = PETSC_BOOL3_TRUE;
5905       mat->symmetric              = PETSC_BOOL3_TRUE;
5906       mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5907     } else {
5908       mat->spd = PETSC_BOOL3_FALSE;
5909     }
5910     break;
5911   case MAT_SYMMETRIC:
5912     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5913     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5914 #if !defined(PETSC_USE_COMPLEX)
5915     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5916 #endif
5917     break;
5918   case MAT_HERMITIAN:
5919     mat->hermitian = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5920     if (flg) mat->structurally_symmetric = PETSC_BOOL3_TRUE;
5921 #if !defined(PETSC_USE_COMPLEX)
5922     mat->symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5923 #endif
5924     break;
5925   case MAT_STRUCTURALLY_SYMMETRIC:
5926     mat->structurally_symmetric = flg ? PETSC_BOOL3_TRUE : PETSC_BOOL3_FALSE;
5927     break;
5928   case MAT_SYMMETRY_ETERNAL:
5929     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");
5930     mat->symmetry_eternal = flg;
5931     if (flg) mat->structural_symmetry_eternal = PETSC_TRUE;
5932     break;
5933   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
5934     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");
5935     mat->structural_symmetry_eternal = flg;
5936     break;
5937   case MAT_SPD_ETERNAL:
5938     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");
5939     mat->spd_eternal = flg;
5940     if (flg) {
5941       mat->structural_symmetry_eternal = PETSC_TRUE;
5942       mat->symmetry_eternal            = PETSC_TRUE;
5943     }
5944     break;
5945   case MAT_STRUCTURE_ONLY:
5946     mat->structure_only = flg;
5947     break;
5948   case MAT_SORTED_FULL:
5949     mat->sortedfull = flg;
5950     break;
5951   default:
5952     break;
5953   }
5954   PetscTryTypeMethod(mat, setoption, op, flg);
5955   PetscFunctionReturn(PETSC_SUCCESS);
5956 }
5957 
5958 /*@
5959    MatGetOption - Gets a parameter option that has been set for a matrix.
5960 
5961    Logically Collective
5962 
5963    Input Parameters:
5964 +  mat - the matrix
5965 -  option - the option, this only responds to certain options, check the code for which ones
5966 
5967    Output Parameter:
5968 .  flg - turn the option on (`PETSC_TRUE`) or off (`PETSC_FALSE`)
5969 
5970    Level: intermediate
5971 
5972     Notes:
5973     Can only be called after `MatSetSizes()` and `MatSetType()` have been set.
5974 
5975     Certain option values may be unknown, for those use the routines `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, or
5976     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5977 
5978 .seealso: [](chapter_matrices), `Mat`, `MatOption`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`,
5979     `MatIsSymmetricKnown()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetricKnown()`
5980 @*/
5981 PetscErrorCode MatGetOption(Mat mat, MatOption op, PetscBool *flg)
5982 {
5983   PetscFunctionBegin;
5984   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
5985   PetscValidType(mat, 1);
5986 
5987   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);
5988   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()");
5989 
5990   switch (op) {
5991   case MAT_NO_OFF_PROC_ENTRIES:
5992     *flg = mat->nooffprocentries;
5993     break;
5994   case MAT_NO_OFF_PROC_ZERO_ROWS:
5995     *flg = mat->nooffproczerorows;
5996     break;
5997   case MAT_SYMMETRIC:
5998     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSymmetric() or MatIsSymmetricKnown()");
5999     break;
6000   case MAT_HERMITIAN:
6001     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsHermitian() or MatIsHermitianKnown()");
6002     break;
6003   case MAT_STRUCTURALLY_SYMMETRIC:
6004     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsStructurallySymmetric() or MatIsStructurallySymmetricKnown()");
6005     break;
6006   case MAT_SPD:
6007     SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "Use MatIsSPDKnown()");
6008     break;
6009   case MAT_SYMMETRY_ETERNAL:
6010     *flg = mat->symmetry_eternal;
6011     break;
6012   case MAT_STRUCTURAL_SYMMETRY_ETERNAL:
6013     *flg = mat->symmetry_eternal;
6014     break;
6015   default:
6016     break;
6017   }
6018   PetscFunctionReturn(PETSC_SUCCESS);
6019 }
6020 
6021 /*@
6022    MatZeroEntries - Zeros all entries of a matrix.  For sparse matrices
6023    this routine retains the old nonzero structure.
6024 
6025    Logically Collective
6026 
6027    Input Parameter:
6028 .  mat - the matrix
6029 
6030    Level: intermediate
6031 
6032    Note:
6033     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.
6034    See the Performance chapter of the users manual for information on preallocating matrices.
6035 
6036 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`
6037 @*/
6038 PetscErrorCode MatZeroEntries(Mat mat)
6039 {
6040   PetscFunctionBegin;
6041   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6042   PetscValidType(mat, 1);
6043   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6044   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");
6045   MatCheckPreallocated(mat, 1);
6046 
6047   PetscCall(PetscLogEventBegin(MAT_ZeroEntries, mat, 0, 0, 0));
6048   PetscUseTypeMethod(mat, zeroentries);
6049   PetscCall(PetscLogEventEnd(MAT_ZeroEntries, mat, 0, 0, 0));
6050   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6051   PetscFunctionReturn(PETSC_SUCCESS);
6052 }
6053 
6054 /*@
6055    MatZeroRowsColumns - Zeros all entries (except possibly the main diagonal)
6056    of a set of rows and columns of a matrix.
6057 
6058    Collective
6059 
6060    Input Parameters:
6061 +  mat - the matrix
6062 .  numRows - the number of rows/columns to zero
6063 .  rows - the global row indices
6064 .  diag - value put in the diagonal of the eliminated rows
6065 .  x - optional vector of the solution for zeroed rows (other entries in vector are not used), these must be set before this call
6066 -  b - optional vector of the right hand side, that will be adjusted by provided solution entries
6067 
6068    Level: intermediate
6069 
6070    Notes:
6071    This routine, along with `MatZeroRows()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6072 
6073    For each zeroed row, the value of the corresponding `b` is set to diag times the value of the corresponding `x`.
6074    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
6075 
6076    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6077    Krylov method to take advantage of the known solution on the zeroed rows.
6078 
6079    For the parallel case, all processes that share the matrix (i.e.,
6080    those in the communicator used for matrix creation) MUST call this
6081    routine, regardless of whether any rows being zeroed are owned by
6082    them.
6083 
6084    Unlike `MatZeroRows()` this does not change the nonzero structure of the matrix, it merely zeros those entries in the matrix.
6085 
6086    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6087    list only rows local to itself).
6088 
6089    The option `MAT_NO_OFF_PROC_ZERO_ROWS` does not apply to this routine.
6090 
6091 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRows()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6092           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6093 @*/
6094 PetscErrorCode MatZeroRowsColumns(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6095 {
6096   PetscFunctionBegin;
6097   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6098   PetscValidType(mat, 1);
6099   if (numRows) PetscValidIntPointer(rows, 3);
6100   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6101   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6102   MatCheckPreallocated(mat, 1);
6103 
6104   PetscUseTypeMethod(mat, zerorowscolumns, numRows, rows, diag, x, b);
6105   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6106   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6107   PetscFunctionReturn(PETSC_SUCCESS);
6108 }
6109 
6110 /*@
6111    MatZeroRowsColumnsIS - Zeros all entries (except possibly the main diagonal)
6112    of a set of rows and columns of a matrix.
6113 
6114    Collective
6115 
6116    Input Parameters:
6117 +  mat - the matrix
6118 .  is - the rows to zero
6119 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6120 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6121 -  b - optional vector of right hand side, that will be adjusted by provided solution
6122 
6123    Level: intermediate
6124 
6125    Note:
6126    See `MatZeroRowsColumns()` for details on how this routine operates.
6127 
6128 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6129           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRows()`, `MatZeroRowsColumnsStencil()`
6130 @*/
6131 PetscErrorCode MatZeroRowsColumnsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6132 {
6133   PetscInt        numRows;
6134   const PetscInt *rows;
6135 
6136   PetscFunctionBegin;
6137   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6138   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6139   PetscValidType(mat, 1);
6140   PetscValidType(is, 2);
6141   PetscCall(ISGetLocalSize(is, &numRows));
6142   PetscCall(ISGetIndices(is, &rows));
6143   PetscCall(MatZeroRowsColumns(mat, numRows, rows, diag, x, b));
6144   PetscCall(ISRestoreIndices(is, &rows));
6145   PetscFunctionReturn(PETSC_SUCCESS);
6146 }
6147 
6148 /*@
6149    MatZeroRows - Zeros all entries (except possibly the main diagonal)
6150    of a set of rows of a matrix.
6151 
6152    Collective
6153 
6154    Input Parameters:
6155 +  mat - the matrix
6156 .  numRows - the number of rows to zero
6157 .  rows - the global row indices
6158 .  diag - value put in the diagonal of the zeroed rows
6159 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used), these must be set before this call
6160 -  b - optional vector of right hand side, that will be adjusted by provided solution entries
6161 
6162    Level: intermediate
6163 
6164    Notes:
6165    This routine, along with `MatZeroRowsColumns()`, is typically used to eliminate known Dirichlet boundary conditions from a linear system.
6166 
6167    For each zeroed row, the value of the corresponding `b` is set to `diag` times the value of the corresponding `x`.
6168 
6169    If the resulting linear system is to be solved with `KSP` then one can (but does not have to) call `KSPSetInitialGuessNonzero()` to allow the
6170    Krylov method to take advantage of the known solution on the zeroed rows.
6171 
6172    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)
6173    from the matrix.
6174 
6175    Unlike `MatZeroRowsColumns()` for the `MATAIJ` and `MATBAIJ` matrix formats this removes the old nonzero structure, from the eliminated rows of the matrix
6176    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
6177    formats this does not alter the nonzero structure.
6178 
6179    If the option `MatSetOption`(mat,`MAT_KEEP_NONZERO_PATTERN`,`PETSC_TRUE`) the nonzero structure
6180    of the matrix is not changed the values are
6181    merely zeroed.
6182 
6183    The user can set a value in the diagonal entry (or for the `MATAIJ` format
6184    formats can optionally remove the main diagonal entry from the
6185    nonzero structure as well, by passing 0.0 as the final argument).
6186 
6187    For the parallel case, all processes that share the matrix (i.e.,
6188    those in the communicator used for matrix creation) MUST call this
6189    routine, regardless of whether any rows being zeroed are owned by
6190    them.
6191 
6192    Each processor can indicate any rows in the entire matrix to be zeroed (i.e. each process does NOT have to
6193    list only rows local to itself).
6194 
6195    You can call `MatSetOption`(mat,`MAT_NO_OFF_PROC_ZERO_ROWS`,`PETSC_TRUE`) if each process indicates only rows it
6196    owns that are to be zeroed. This saves a global synchronization in the implementation.
6197 
6198 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6199           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`, `PCREDISTRIBUTE`
6200 @*/
6201 PetscErrorCode MatZeroRows(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6202 {
6203   PetscFunctionBegin;
6204   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6205   PetscValidType(mat, 1);
6206   if (numRows) PetscValidIntPointer(rows, 3);
6207   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6208   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6209   MatCheckPreallocated(mat, 1);
6210 
6211   PetscUseTypeMethod(mat, zerorows, numRows, rows, diag, x, b);
6212   PetscCall(MatViewFromOptions(mat, NULL, "-mat_view"));
6213   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6214   PetscFunctionReturn(PETSC_SUCCESS);
6215 }
6216 
6217 /*@
6218    MatZeroRowsIS - Zeros all entries (except possibly the main diagonal)
6219    of a set of rows of a matrix.
6220 
6221    Collective
6222 
6223    Input Parameters:
6224 +  mat - the matrix
6225 .  is - index set of rows to remove (if `NULL` then no row is removed)
6226 .  diag - value put in all diagonals of eliminated rows
6227 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6228 -  b - optional vector of right hand side, that will be adjusted by provided solution
6229 
6230    Level: intermediate
6231 
6232    Note:
6233    See `MatZeroRows()` for details on how this routine operates.
6234 
6235 .seealso: [](chapter_matrices), `Mat`, `MatZeroRows()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6236           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6237 @*/
6238 PetscErrorCode MatZeroRowsIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6239 {
6240   PetscInt        numRows = 0;
6241   const PetscInt *rows    = NULL;
6242 
6243   PetscFunctionBegin;
6244   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6245   PetscValidType(mat, 1);
6246   if (is) {
6247     PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6248     PetscCall(ISGetLocalSize(is, &numRows));
6249     PetscCall(ISGetIndices(is, &rows));
6250   }
6251   PetscCall(MatZeroRows(mat, numRows, rows, diag, x, b));
6252   if (is) PetscCall(ISRestoreIndices(is, &rows));
6253   PetscFunctionReturn(PETSC_SUCCESS);
6254 }
6255 
6256 /*@
6257    MatZeroRowsStencil - Zeros all entries (except possibly the main diagonal)
6258    of a set of rows of a matrix. These rows must be local to the process.
6259 
6260    Collective
6261 
6262    Input Parameters:
6263 +  mat - the matrix
6264 .  numRows - the number of rows to remove
6265 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6266 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6267 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6268 -  b - optional vector of right hand side, that will be adjusted by provided solution
6269 
6270    Level: intermediate
6271 
6272    Notes:
6273    See `MatZeroRows()` for details on how this routine operates.
6274 
6275    The grid coordinates are across the entire grid, not just the local portion
6276 
6277    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6278    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6279    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6280    `DM_BOUNDARY_PERIODIC` boundary type.
6281 
6282    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
6283    a single value per point) you can skip filling those indices.
6284 
6285    Fortran Note:
6286    `idxm` and `idxn` should be declared as
6287 $     MatStencil idxm(4, m)
6288    and the values inserted using
6289 .vb
6290     idxm(MatStencil_i, 1) = i
6291     idxm(MatStencil_j, 1) = j
6292     idxm(MatStencil_k, 1) = k
6293     idxm(MatStencil_c, 1) = c
6294    etc
6295 .ve
6296 
6297 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsl()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6298           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6299 @*/
6300 PetscErrorCode MatZeroRowsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6301 {
6302   PetscInt  dim    = mat->stencil.dim;
6303   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6304   PetscInt *dims   = mat->stencil.dims + 1;
6305   PetscInt *starts = mat->stencil.starts;
6306   PetscInt *dxm    = (PetscInt *)rows;
6307   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6308 
6309   PetscFunctionBegin;
6310   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6311   PetscValidType(mat, 1);
6312   if (numRows) PetscValidPointer(rows, 3);
6313 
6314   PetscCall(PetscMalloc1(numRows, &jdxm));
6315   for (i = 0; i < numRows; ++i) {
6316     /* Skip unused dimensions (they are ordered k, j, i, c) */
6317     for (j = 0; j < 3 - sdim; ++j) dxm++;
6318     /* Local index in X dir */
6319     tmp = *dxm++ - starts[0];
6320     /* Loop over remaining dimensions */
6321     for (j = 0; j < dim - 1; ++j) {
6322       /* If nonlocal, set index to be negative */
6323       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6324       /* Update local index */
6325       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6326     }
6327     /* Skip component slot if necessary */
6328     if (mat->stencil.noc) dxm++;
6329     /* Local row number */
6330     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6331   }
6332   PetscCall(MatZeroRowsLocal(mat, numNewRows, jdxm, diag, x, b));
6333   PetscCall(PetscFree(jdxm));
6334   PetscFunctionReturn(PETSC_SUCCESS);
6335 }
6336 
6337 /*@
6338    MatZeroRowsColumnsStencil - Zeros all row and column entries (except possibly the main diagonal)
6339    of a set of rows and columns of a matrix.
6340 
6341    Collective
6342 
6343    Input Parameters:
6344 +  mat - the matrix
6345 .  numRows - the number of rows/columns to remove
6346 .  rows - the grid coordinates (and component number when dof > 1) for matrix rows
6347 .  diag - value put in all diagonals of eliminated rows (0.0 will even eliminate diagonal entry)
6348 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6349 -  b - optional vector of right hand side, that will be adjusted by provided solution
6350 
6351    Level: intermediate
6352 
6353    Notes:
6354    See `MatZeroRowsColumns()` for details on how this routine operates.
6355 
6356    The grid coordinates are across the entire grid, not just the local portion
6357 
6358    For periodic boundary conditions use negative indices for values to the left (below 0; that are to be
6359    obtained by wrapping values from right edge). For values to the right of the last entry using that index plus one
6360    etc to obtain values that obtained by wrapping the values from the left edge. This does not work for anything but the
6361    `DM_BOUNDARY_PERIODIC` boundary type.
6362 
6363    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
6364    a single value per point) you can skip filling those indices.
6365 
6366    Fortran Note:
6367    `idxm` and `idxn` should be declared as
6368 $     MatStencil idxm(4, m)
6369    and the values inserted using
6370 .vb
6371     idxm(MatStencil_i, 1) = i
6372     idxm(MatStencil_j, 1) = j
6373     idxm(MatStencil_k, 1) = k
6374     idxm(MatStencil_c, 1) = c
6375     etc
6376 .ve
6377 
6378 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6379           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRows()`
6380 @*/
6381 PetscErrorCode MatZeroRowsColumnsStencil(Mat mat, PetscInt numRows, const MatStencil rows[], PetscScalar diag, Vec x, Vec b)
6382 {
6383   PetscInt  dim    = mat->stencil.dim;
6384   PetscInt  sdim   = dim - (1 - (PetscInt)mat->stencil.noc);
6385   PetscInt *dims   = mat->stencil.dims + 1;
6386   PetscInt *starts = mat->stencil.starts;
6387   PetscInt *dxm    = (PetscInt *)rows;
6388   PetscInt *jdxm, i, j, tmp, numNewRows = 0;
6389 
6390   PetscFunctionBegin;
6391   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6392   PetscValidType(mat, 1);
6393   if (numRows) PetscValidPointer(rows, 3);
6394 
6395   PetscCall(PetscMalloc1(numRows, &jdxm));
6396   for (i = 0; i < numRows; ++i) {
6397     /* Skip unused dimensions (they are ordered k, j, i, c) */
6398     for (j = 0; j < 3 - sdim; ++j) dxm++;
6399     /* Local index in X dir */
6400     tmp = *dxm++ - starts[0];
6401     /* Loop over remaining dimensions */
6402     for (j = 0; j < dim - 1; ++j) {
6403       /* If nonlocal, set index to be negative */
6404       if ((*dxm++ - starts[j + 1]) < 0 || tmp < 0) tmp = PETSC_MIN_INT;
6405       /* Update local index */
6406       else tmp = tmp * dims[j] + *(dxm - 1) - starts[j + 1];
6407     }
6408     /* Skip component slot if necessary */
6409     if (mat->stencil.noc) dxm++;
6410     /* Local row number */
6411     if (tmp >= 0) jdxm[numNewRows++] = tmp;
6412   }
6413   PetscCall(MatZeroRowsColumnsLocal(mat, numNewRows, jdxm, diag, x, b));
6414   PetscCall(PetscFree(jdxm));
6415   PetscFunctionReturn(PETSC_SUCCESS);
6416 }
6417 
6418 /*@C
6419    MatZeroRowsLocal - Zeros all entries (except possibly the main diagonal)
6420    of a set of rows of a matrix; using local numbering of rows.
6421 
6422    Collective
6423 
6424    Input Parameters:
6425 +  mat - the matrix
6426 .  numRows - the number of rows to remove
6427 .  rows - the local row indices
6428 .  diag - value put in all diagonals of eliminated rows
6429 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6430 -  b - optional vector of right hand side, that will be adjusted by provided solution
6431 
6432    Level: intermediate
6433 
6434    Notes:
6435    Before calling `MatZeroRowsLocal()`, the user must first set the
6436    local-to-global mapping by calling MatSetLocalToGlobalMapping(), this is often already set for matrices obtained with `DMCreateMatrix()`.
6437 
6438    See `MatZeroRows()` for details on how this routine operates.
6439 
6440 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRows()`, `MatSetOption()`,
6441           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6442 @*/
6443 PetscErrorCode MatZeroRowsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6444 {
6445   PetscFunctionBegin;
6446   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6447   PetscValidType(mat, 1);
6448   if (numRows) PetscValidIntPointer(rows, 3);
6449   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6450   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6451   MatCheckPreallocated(mat, 1);
6452 
6453   if (mat->ops->zerorowslocal) {
6454     PetscUseTypeMethod(mat, zerorowslocal, numRows, rows, diag, x, b);
6455   } else {
6456     IS              is, newis;
6457     const PetscInt *newRows;
6458 
6459     PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6460     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6461     PetscCall(ISLocalToGlobalMappingApplyIS(mat->rmap->mapping, is, &newis));
6462     PetscCall(ISGetIndices(newis, &newRows));
6463     PetscUseTypeMethod(mat, zerorows, numRows, newRows, diag, x, b);
6464     PetscCall(ISRestoreIndices(newis, &newRows));
6465     PetscCall(ISDestroy(&newis));
6466     PetscCall(ISDestroy(&is));
6467   }
6468   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6469   PetscFunctionReturn(PETSC_SUCCESS);
6470 }
6471 
6472 /*@
6473    MatZeroRowsLocalIS - Zeros all entries (except possibly the main diagonal)
6474    of a set of rows of a matrix; using local numbering of rows.
6475 
6476    Collective
6477 
6478    Input Parameters:
6479 +  mat - the matrix
6480 .  is - index set of rows to remove
6481 .  diag - value put in all diagonals of eliminated rows
6482 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6483 -  b - optional vector of right hand side, that will be adjusted by provided solution
6484 
6485    Level: intermediate
6486 
6487    Notes:
6488    Before calling `MatZeroRowsLocalIS()`, the user must first set the
6489    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6490 
6491    See `MatZeroRows()` for details on how this routine operates.
6492 
6493 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRows()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6494           `MatZeroRowsColumnsLocal()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6495 @*/
6496 PetscErrorCode MatZeroRowsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6497 {
6498   PetscInt        numRows;
6499   const PetscInt *rows;
6500 
6501   PetscFunctionBegin;
6502   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6503   PetscValidType(mat, 1);
6504   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6505   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6506   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6507   MatCheckPreallocated(mat, 1);
6508 
6509   PetscCall(ISGetLocalSize(is, &numRows));
6510   PetscCall(ISGetIndices(is, &rows));
6511   PetscCall(MatZeroRowsLocal(mat, numRows, rows, diag, x, b));
6512   PetscCall(ISRestoreIndices(is, &rows));
6513   PetscFunctionReturn(PETSC_SUCCESS);
6514 }
6515 
6516 /*@
6517    MatZeroRowsColumnsLocal - Zeros all entries (except possibly the main diagonal)
6518    of a set of rows and columns of a matrix; using local numbering of rows.
6519 
6520    Collective
6521 
6522    Input Parameters:
6523 +  mat - the matrix
6524 .  numRows - the number of rows to remove
6525 .  rows - the global row indices
6526 .  diag - value put in all diagonals of eliminated rows
6527 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6528 -  b - optional vector of right hand side, that will be adjusted by provided solution
6529 
6530    Level: intermediate
6531 
6532    Notes:
6533    Before calling `MatZeroRowsColumnsLocal()`, the user must first set the
6534    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6535 
6536    See `MatZeroRowsColumns()` for details on how this routine operates.
6537 
6538 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6539           `MatZeroRows()`, `MatZeroRowsColumnsLocalIS()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6540 @*/
6541 PetscErrorCode MatZeroRowsColumnsLocal(Mat mat, PetscInt numRows, const PetscInt rows[], PetscScalar diag, Vec x, Vec b)
6542 {
6543   IS              is, newis;
6544   const PetscInt *newRows;
6545 
6546   PetscFunctionBegin;
6547   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6548   PetscValidType(mat, 1);
6549   if (numRows) PetscValidIntPointer(rows, 3);
6550   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6551   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6552   MatCheckPreallocated(mat, 1);
6553 
6554   PetscCheck(mat->cmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Need to provide local to global mapping to matrix first");
6555   PetscCall(ISCreateGeneral(PETSC_COMM_SELF, numRows, rows, PETSC_COPY_VALUES, &is));
6556   PetscCall(ISLocalToGlobalMappingApplyIS(mat->cmap->mapping, is, &newis));
6557   PetscCall(ISGetIndices(newis, &newRows));
6558   PetscUseTypeMethod(mat, zerorowscolumns, numRows, newRows, diag, x, b);
6559   PetscCall(ISRestoreIndices(newis, &newRows));
6560   PetscCall(ISDestroy(&newis));
6561   PetscCall(ISDestroy(&is));
6562   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
6563   PetscFunctionReturn(PETSC_SUCCESS);
6564 }
6565 
6566 /*@
6567    MatZeroRowsColumnsLocalIS - Zeros all entries (except possibly the main diagonal)
6568    of a set of rows and columns of a matrix; using local numbering of rows.
6569 
6570    Collective
6571 
6572    Input Parameters:
6573 +  mat - the matrix
6574 .  is - index set of rows to remove
6575 .  diag - value put in all diagonals of eliminated rows
6576 .  x - optional vector of solutions for zeroed rows (other entries in vector are not used)
6577 -  b - optional vector of right hand side, that will be adjusted by provided solution
6578 
6579    Level: intermediate
6580 
6581    Notes:
6582    Before calling `MatZeroRowsColumnsLocalIS()`, the user must first set the
6583    local-to-global mapping by calling `MatSetLocalToGlobalMapping()`, this is often already set for matrices obtained with `DMCreateMatrix()`.
6584 
6585    See `MatZeroRowsColumns()` for details on how this routine operates.
6586 
6587 .seealso: [](chapter_matrices), `Mat`, `MatZeroRowsIS()`, `MatZeroRowsColumns()`, `MatZeroRowsLocalIS()`, `MatZeroRowsStencil()`, `MatZeroEntries()`, `MatZeroRowsLocal()`, `MatSetOption()`,
6588           `MatZeroRowsColumnsLocal()`, `MatZeroRows()`, `MatZeroRowsColumnsIS()`, `MatZeroRowsColumnsStencil()`
6589 @*/
6590 PetscErrorCode MatZeroRowsColumnsLocalIS(Mat mat, IS is, PetscScalar diag, Vec x, Vec b)
6591 {
6592   PetscInt        numRows;
6593   const PetscInt *rows;
6594 
6595   PetscFunctionBegin;
6596   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6597   PetscValidType(mat, 1);
6598   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
6599   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6600   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6601   MatCheckPreallocated(mat, 1);
6602 
6603   PetscCall(ISGetLocalSize(is, &numRows));
6604   PetscCall(ISGetIndices(is, &rows));
6605   PetscCall(MatZeroRowsColumnsLocal(mat, numRows, rows, diag, x, b));
6606   PetscCall(ISRestoreIndices(is, &rows));
6607   PetscFunctionReturn(PETSC_SUCCESS);
6608 }
6609 
6610 /*@C
6611    MatGetSize - Returns the numbers of rows and columns in a matrix.
6612 
6613    Not Collective
6614 
6615    Input Parameter:
6616 .  mat - the matrix
6617 
6618    Output Parameters:
6619 +  m - the number of global rows
6620 -  n - the number of global columns
6621 
6622    Level: beginner
6623 
6624    Note:
6625    Both output parameters can be `NULL` on input.
6626 
6627 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetLocalSize()`
6628 @*/
6629 PetscErrorCode MatGetSize(Mat mat, PetscInt *m, PetscInt *n)
6630 {
6631   PetscFunctionBegin;
6632   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6633   if (m) *m = mat->rmap->N;
6634   if (n) *n = mat->cmap->N;
6635   PetscFunctionReturn(PETSC_SUCCESS);
6636 }
6637 
6638 /*@C
6639    MatGetLocalSize - For most matrix formats, excluding `MATELEMENTAL` and `MATSCALAPACK`, Returns the number of local rows and local columns
6640    of a matrix. For all matrices this is the local size of the left and right vectors as returned by `MatCreateVecs()`.
6641 
6642    Not Collective
6643 
6644    Input Parameter:
6645 .  mat - the matrix
6646 
6647    Output Parameters:
6648 +  m - the number of local rows, use `NULL` to not obtain this value
6649 -  n - the number of local columns, use `NULL` to not obtain this value
6650 
6651    Level: beginner
6652 
6653 .seealso: [](chapter_matrices), `Mat`, `MatSetSizes()`, `MatGetSize()`
6654 @*/
6655 PetscErrorCode MatGetLocalSize(Mat mat, PetscInt *m, PetscInt *n)
6656 {
6657   PetscFunctionBegin;
6658   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6659   if (m) PetscValidIntPointer(m, 2);
6660   if (n) PetscValidIntPointer(n, 3);
6661   if (m) *m = mat->rmap->n;
6662   if (n) *n = mat->cmap->n;
6663   PetscFunctionReturn(PETSC_SUCCESS);
6664 }
6665 
6666 /*@C
6667    MatGetOwnershipRangeColumn - Returns the range of matrix columns associated with rows of a vector one multiplies this matrix by that are owned by
6668    this processor. (The columns of the "diagonal block" for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6669 
6670    Not Collective, unless matrix has not been allocated, then collective
6671 
6672    Input Parameter:
6673 .  mat - the matrix
6674 
6675    Output Parameters:
6676 +  m - the global index of the first local column, use `NULL` to not obtain this value
6677 -  n - one more than the global index of the last local column, use `NULL` to not obtain this value
6678 
6679    Level: developer
6680 
6681 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6682 @*/
6683 PetscErrorCode MatGetOwnershipRangeColumn(Mat mat, PetscInt *m, PetscInt *n)
6684 {
6685   PetscFunctionBegin;
6686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6687   PetscValidType(mat, 1);
6688   if (m) PetscValidIntPointer(m, 2);
6689   if (n) PetscValidIntPointer(n, 3);
6690   MatCheckPreallocated(mat, 1);
6691   if (m) *m = mat->cmap->rstart;
6692   if (n) *n = mat->cmap->rend;
6693   PetscFunctionReturn(PETSC_SUCCESS);
6694 }
6695 
6696 /*@C
6697    MatGetOwnershipRange - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6698    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
6699    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6700 
6701    Not Collective
6702 
6703    Input Parameter:
6704 .  mat - the matrix
6705 
6706    Output Parameters:
6707 +  m - the global index of the first local row, use `NULL` to not obtain this value
6708 -  n - one more than the global index of the last local row, use `NULL` to not obtain this value
6709 
6710    Level: beginner
6711 
6712    Note:
6713   This function requires that the matrix be preallocated. If you have not preallocated, consider using
6714   `PetscSplitOwnership`(`MPI_Comm` comm, `PetscInt` *n, `PetscInt` *N)
6715   and then `MPI_Scan()` to calculate prefix sums of the local sizes.
6716 
6717 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRanges()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscSplitOwnership()`, `PetscSplitOwnershipBlock()`,
6718           `PetscLayout`
6719 @*/
6720 PetscErrorCode MatGetOwnershipRange(Mat mat, PetscInt *m, PetscInt *n)
6721 {
6722   PetscFunctionBegin;
6723   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6724   PetscValidType(mat, 1);
6725   if (m) PetscValidIntPointer(m, 2);
6726   if (n) PetscValidIntPointer(n, 3);
6727   MatCheckPreallocated(mat, 1);
6728   if (m) *m = mat->rmap->rstart;
6729   if (n) *n = mat->rmap->rend;
6730   PetscFunctionReturn(PETSC_SUCCESS);
6731 }
6732 
6733 /*@C
6734    MatGetOwnershipRanges - For matrices that own values by row, excludes `MATELEMENTAL` and `MATSCALAPACK`, returns the range of matrix rows owned by
6735    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
6736    vector product with this matrix. See :any:`<sec_matlayout>` for details on matrix layouts
6737 
6738    Not Collective, unless matrix has not been allocated
6739 
6740    Input Parameter:
6741 .  mat - the matrix
6742 
6743    Output Parameter:
6744 .  ranges - start of each processors portion plus one more than the total length at the end
6745 
6746    Level: beginner
6747 
6748 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRangesColumn()`, `PetscLayout`
6749 @*/
6750 PetscErrorCode MatGetOwnershipRanges(Mat mat, const PetscInt **ranges)
6751 {
6752   PetscFunctionBegin;
6753   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6754   PetscValidType(mat, 1);
6755   MatCheckPreallocated(mat, 1);
6756   PetscCall(PetscLayoutGetRanges(mat->rmap, ranges));
6757   PetscFunctionReturn(PETSC_SUCCESS);
6758 }
6759 
6760 /*@C
6761    MatGetOwnershipRangesColumn - Returns the ranges of matrix columns associated with rows of a vector one multiplies this vector by that are owned by
6762    each processor. (The columns of the "diagonal blocks", for most sparse matrix formats). See :any:`<sec_matlayout>` for details on matrix layouts.
6763 
6764    Not Collective, unless matrix has not been allocated
6765 
6766    Input Parameter:
6767 .  mat - the matrix
6768 
6769    Output Parameter:
6770 .  ranges - start of each processors portion plus one more then the total length at the end
6771 
6772    Level: beginner
6773 
6774 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatGetOwnershipRanges()`
6775 @*/
6776 PetscErrorCode MatGetOwnershipRangesColumn(Mat mat, const PetscInt **ranges)
6777 {
6778   PetscFunctionBegin;
6779   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6780   PetscValidType(mat, 1);
6781   MatCheckPreallocated(mat, 1);
6782   PetscCall(PetscLayoutGetRanges(mat->cmap, ranges));
6783   PetscFunctionReturn(PETSC_SUCCESS);
6784 }
6785 
6786 /*@C
6787    MatGetOwnershipIS - Get row and column ownership of a matrices' values as index sets. For most matrices, excluding `MATELEMENTAL` and `MATSCALAPACK`, this
6788    corresponds to values returned by `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`. For `MATELEMENTAL` and `MATSCALAPACK` the ownership
6789    is more complicated. See :any:`<sec_matlayout>` for details on matrix layouts.
6790 
6791    Not Collective
6792 
6793    Input Parameter:
6794 .  A - matrix
6795 
6796    Output Parameters:
6797 +  rows - rows in which this process owns elements, , use `NULL` to not obtain this value
6798 -  cols - columns in which this process owns elements, use `NULL` to not obtain this value
6799 
6800    Level: intermediate
6801 
6802 .seealso: [](chapter_matrices), `Mat`, `MatGetOwnershipRange()`, `MatGetOwnershipRangeColumn()`, `MatSetValues()`, ``MATELEMENTAL``, ``MATSCALAPACK``
6803 @*/
6804 PetscErrorCode MatGetOwnershipIS(Mat A, IS *rows, IS *cols)
6805 {
6806   PetscErrorCode (*f)(Mat, IS *, IS *);
6807 
6808   PetscFunctionBegin;
6809   MatCheckPreallocated(A, 1);
6810   PetscCall(PetscObjectQueryFunction((PetscObject)A, "MatGetOwnershipIS_C", &f));
6811   if (f) {
6812     PetscCall((*f)(A, rows, cols));
6813   } else { /* Create a standard row-based partition, each process is responsible for ALL columns in their row block */
6814     if (rows) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->rmap->n, A->rmap->rstart, 1, rows));
6815     if (cols) PetscCall(ISCreateStride(PETSC_COMM_SELF, A->cmap->N, 0, 1, cols));
6816   }
6817   PetscFunctionReturn(PETSC_SUCCESS);
6818 }
6819 
6820 /*@C
6821    MatILUFactorSymbolic - Performs symbolic ILU factorization of a matrix obtained with `MatGetFactor()`
6822    Uses levels of fill only, not drop tolerance. Use `MatLUFactorNumeric()`
6823    to complete the factorization.
6824 
6825    Collective
6826 
6827    Input Parameters:
6828 +  fact - the factorized matrix obtained with `MatGetFactor()`
6829 .  mat - the matrix
6830 .  row - row permutation
6831 .  col - column permutation
6832 -  info - structure containing
6833 .vb
6834       levels - number of levels of fill.
6835       expected fill - as ratio of original fill.
6836       1 or 0 - indicating force fill on diagonal (improves robustness for matrices
6837                 missing diagonal entries)
6838 .ve
6839 
6840    Level: developer
6841 
6842    Notes:
6843    See [Matrix Factorization](sec_matfactor) for additional information.
6844 
6845    Most users should employ the `KSP` interface for linear solvers
6846    instead of working directly with matrix algebra routines such as this.
6847    See, e.g., `KSPCreate()`.
6848 
6849    Uses the definition of level of fill as in Y. Saad, 2003
6850 
6851    Developer Note:
6852    The Fortran interface is not autogenerated as the
6853    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6854 
6855    References:
6856 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6857 
6858 .seealso: [](chapter_matrices), `Mat`, [Matrix Factorization](sec_matfactor), `MatGetFactor()`, `MatLUFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
6859           `MatGetOrdering()`, `MatFactorInfo`
6860 @*/
6861 PetscErrorCode MatILUFactorSymbolic(Mat fact, Mat mat, IS row, IS col, const MatFactorInfo *info)
6862 {
6863   PetscFunctionBegin;
6864   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6865   PetscValidType(mat, 2);
6866   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 3);
6867   if (col) PetscValidHeaderSpecific(col, IS_CLASSID, 4);
6868   PetscValidPointer(info, 5);
6869   PetscValidPointer(fact, 1);
6870   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels of fill negative %" PetscInt_FMT, (PetscInt)info->levels);
6871   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6872   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6873   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6874   MatCheckPreallocated(mat, 2);
6875 
6876   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ILUFactorSymbolic, mat, row, col, 0));
6877   PetscUseTypeMethod(fact, ilufactorsymbolic, mat, row, col, info);
6878   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ILUFactorSymbolic, mat, row, col, 0));
6879   PetscFunctionReturn(PETSC_SUCCESS);
6880 }
6881 
6882 /*@C
6883    MatICCFactorSymbolic - Performs symbolic incomplete
6884    Cholesky factorization for a symmetric matrix.  Use
6885    `MatCholeskyFactorNumeric()` to complete the factorization.
6886 
6887    Collective
6888 
6889    Input Parameters:
6890 +  fact - the factorized matrix obtained with `MatGetFactor()`
6891 .  mat - the matrix to be factored
6892 .  perm - row and column permutation
6893 -  info - structure containing
6894 .vb
6895       levels - number of levels of fill.
6896       expected fill - as ratio of original fill.
6897 .ve
6898 
6899    Level: developer
6900 
6901    Notes:
6902    Most users should employ the `KSP` interface for linear solvers
6903    instead of working directly with matrix algebra routines such as this.
6904    See, e.g., `KSPCreate()`.
6905 
6906    This uses the definition of level of fill as in Y. Saad, 2003
6907 
6908    Developer Note:
6909    The Fortran interface is not autogenerated as the
6910    interface definition cannot be generated correctly [due to `MatFactorInfo`]
6911 
6912    References:
6913 .  * - Y. Saad, Iterative methods for sparse linear systems Philadelphia: Society for Industrial and Applied Mathematics, 2003
6914 
6915 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactorNumeric()`, `MatCholeskyFactor()`, `MatFactorInfo`
6916 @*/
6917 PetscErrorCode MatICCFactorSymbolic(Mat fact, Mat mat, IS perm, const MatFactorInfo *info)
6918 {
6919   PetscFunctionBegin;
6920   PetscValidHeaderSpecific(mat, MAT_CLASSID, 2);
6921   PetscValidType(mat, 2);
6922   if (perm) PetscValidHeaderSpecific(perm, IS_CLASSID, 3);
6923   PetscValidPointer(info, 4);
6924   PetscValidPointer(fact, 1);
6925   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
6926   PetscCheck(info->levels >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Levels negative %" PetscInt_FMT, (PetscInt)info->levels);
6927   PetscCheck(info->fill >= 1.0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Expected fill less than 1.0 %g", (double)info->fill);
6928   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
6929   MatCheckPreallocated(mat, 2);
6930 
6931   if (!fact->trivialsymbolic) PetscCall(PetscLogEventBegin(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6932   PetscUseTypeMethod(fact, iccfactorsymbolic, mat, perm, info);
6933   if (!fact->trivialsymbolic) PetscCall(PetscLogEventEnd(MAT_ICCFactorSymbolic, mat, perm, 0, 0));
6934   PetscFunctionReturn(PETSC_SUCCESS);
6935 }
6936 
6937 /*@C
6938    MatCreateSubMatrices - Extracts several submatrices from a matrix. If submat
6939    points to an array of valid matrices, they may be reused to store the new
6940    submatrices.
6941 
6942    Collective
6943 
6944    Input Parameters:
6945 +  mat - the matrix
6946 .  n   - the number of submatrixes to be extracted (on this processor, may be zero)
6947 .  irow - index set of rows to extract
6948 .  icol - index set of columns to extract
6949 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
6950 
6951    Output Parameter:
6952 .  submat - the array of submatrices
6953 
6954    Level: advanced
6955 
6956    Notes:
6957    `MatCreateSubMatrices()` can extract ONLY sequential submatrices
6958    (from both sequential and parallel matrices). Use `MatCreateSubMatrix()`
6959    to extract a parallel submatrix.
6960 
6961    Some matrix types place restrictions on the row and column
6962    indices, such as that they be sorted or that they be equal to each other.
6963 
6964    The index sets may not have duplicate entries.
6965 
6966    When extracting submatrices from a parallel matrix, each processor can
6967    form a different submatrix by setting the rows and columns of its
6968    individual index sets according to the local submatrix desired.
6969 
6970    When finished using the submatrices, the user should destroy
6971    them with `MatDestroySubMatrices()`.
6972 
6973    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
6974    original matrix has not changed from that last call to `MatCreateSubMatrices()`.
6975 
6976    This routine creates the matrices in submat; you should NOT create them before
6977    calling it. It also allocates the array of matrix pointers submat.
6978 
6979    For `MATBAIJ` matrices the index sets must respect the block structure, that is if they
6980    request one row/column in a block, they must request all rows/columns that are in
6981    that block. For example, if the block size is 2 you cannot request just row 0 and
6982    column 0.
6983 
6984    Fortran Note:
6985    The Fortran interface is slightly different from that given below; it
6986    requires one to pass in as `submat` a `Mat` (integer) array of size at least n+1.
6987 
6988 .seealso: [](chapter_matrices), `Mat`, `MatDestroySubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
6989 @*/
6990 PetscErrorCode MatCreateSubMatrices(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
6991 {
6992   PetscInt  i;
6993   PetscBool eq;
6994 
6995   PetscFunctionBegin;
6996   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
6997   PetscValidType(mat, 1);
6998   if (n) {
6999     PetscValidPointer(irow, 3);
7000     for (i = 0; i < n; i++) PetscValidHeaderSpecific(irow[i], IS_CLASSID, 3);
7001     PetscValidPointer(icol, 4);
7002     for (i = 0; i < n; i++) PetscValidHeaderSpecific(icol[i], IS_CLASSID, 4);
7003   }
7004   PetscValidPointer(submat, 6);
7005   if (n && scall == MAT_REUSE_MATRIX) {
7006     PetscValidPointer(*submat, 6);
7007     for (i = 0; i < n; i++) PetscValidHeaderSpecific((*submat)[i], MAT_CLASSID, 6);
7008   }
7009   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7010   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7011   MatCheckPreallocated(mat, 1);
7012   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7013   PetscUseTypeMethod(mat, createsubmatrices, n, irow, icol, scall, submat);
7014   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7015   for (i = 0; i < n; i++) {
7016     (*submat)[i]->factortype = MAT_FACTOR_NONE; /* in case in place factorization was previously done on submatrix */
7017     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7018     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7019 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
7020     if (mat->boundtocpu && mat->bindingpropagates) {
7021       PetscCall(MatBindToCPU((*submat)[i], PETSC_TRUE));
7022       PetscCall(MatSetBindingPropagates((*submat)[i], PETSC_TRUE));
7023     }
7024 #endif
7025   }
7026   PetscFunctionReturn(PETSC_SUCCESS);
7027 }
7028 
7029 /*@C
7030    MatCreateSubMatricesMPI - Extracts MPI submatrices across a sub communicator of mat (by pairs of `IS` that may live on subcomms).
7031 
7032    Collective
7033 
7034    Input Parameters:
7035 +  mat - the matrix
7036 .  n   - the number of submatrixes to be extracted
7037 .  irow - index set of rows to extract
7038 .  icol - index set of columns to extract
7039 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
7040 
7041    Output Parameter:
7042 .  submat - the array of submatrices
7043 
7044    Level: advanced
7045 
7046    Note:
7047    This is used by `PCGASM`
7048 
7049 .seealso: [](chapter_matrices), `Mat`, `PCGASM`, `MatCreateSubMatrices()`, `MatCreateSubMatrix()`, `MatGetRow()`, `MatGetDiagonal()`, `MatReuse`
7050 @*/
7051 PetscErrorCode MatCreateSubMatricesMPI(Mat mat, PetscInt n, const IS irow[], const IS icol[], MatReuse scall, Mat *submat[])
7052 {
7053   PetscInt  i;
7054   PetscBool eq;
7055 
7056   PetscFunctionBegin;
7057   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7058   PetscValidType(mat, 1);
7059   if (n) {
7060     PetscValidPointer(irow, 3);
7061     PetscValidHeaderSpecific(*irow, IS_CLASSID, 3);
7062     PetscValidPointer(icol, 4);
7063     PetscValidHeaderSpecific(*icol, IS_CLASSID, 4);
7064   }
7065   PetscValidPointer(submat, 6);
7066   if (n && scall == MAT_REUSE_MATRIX) {
7067     PetscValidPointer(*submat, 6);
7068     PetscValidHeaderSpecific(**submat, MAT_CLASSID, 6);
7069   }
7070   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7071   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7072   MatCheckPreallocated(mat, 1);
7073 
7074   PetscCall(PetscLogEventBegin(MAT_CreateSubMats, mat, 0, 0, 0));
7075   PetscUseTypeMethod(mat, createsubmatricesmpi, n, irow, icol, scall, submat);
7076   PetscCall(PetscLogEventEnd(MAT_CreateSubMats, mat, 0, 0, 0));
7077   for (i = 0; i < n; i++) {
7078     PetscCall(ISEqualUnsorted(irow[i], icol[i], &eq));
7079     if (eq) PetscCall(MatPropagateSymmetryOptions(mat, (*submat)[i]));
7080   }
7081   PetscFunctionReturn(PETSC_SUCCESS);
7082 }
7083 
7084 /*@C
7085    MatDestroyMatrices - Destroys an array of matrices.
7086 
7087    Collective
7088 
7089    Input Parameters:
7090 +  n - the number of local matrices
7091 -  mat - the matrices (this is a pointer to the array of matrices)
7092 
7093    Level: advanced
7094 
7095     Note:
7096     Frees not only the matrices, but also the array that contains the matrices
7097 
7098     Fortran Note:
7099     This does not free the array.
7100 
7101 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()` `MatDestroySubMatrices()`
7102 @*/
7103 PetscErrorCode MatDestroyMatrices(PetscInt n, Mat *mat[])
7104 {
7105   PetscInt i;
7106 
7107   PetscFunctionBegin;
7108   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7109   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7110   PetscValidPointer(mat, 2);
7111 
7112   for (i = 0; i < n; i++) PetscCall(MatDestroy(&(*mat)[i]));
7113 
7114   /* memory is allocated even if n = 0 */
7115   PetscCall(PetscFree(*mat));
7116   PetscFunctionReturn(PETSC_SUCCESS);
7117 }
7118 
7119 /*@C
7120    MatDestroySubMatrices - Destroys a set of matrices obtained with `MatCreateSubMatrices()`.
7121 
7122    Collective
7123 
7124    Input Parameters:
7125 +  n - the number of local matrices
7126 -  mat - the matrices (this is a pointer to the array of matrices, just to match the calling
7127                        sequence of `MatCreateSubMatrices()`)
7128 
7129    Level: advanced
7130 
7131     Note:
7132     Frees not only the matrices, but also the array that contains the matrices
7133 
7134     Fortran Note:
7135     This does not free the array.
7136 
7137 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7138 @*/
7139 PetscErrorCode MatDestroySubMatrices(PetscInt n, Mat *mat[])
7140 {
7141   Mat mat0;
7142 
7143   PetscFunctionBegin;
7144   if (!*mat) PetscFunctionReturn(PETSC_SUCCESS);
7145   /* mat[] is an array of length n+1, see MatCreateSubMatrices_xxx() */
7146   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Trying to destroy negative number of matrices %" PetscInt_FMT, n);
7147   PetscValidPointer(mat, 2);
7148 
7149   mat0 = (*mat)[0];
7150   if (mat0 && mat0->ops->destroysubmatrices) {
7151     PetscCall((*mat0->ops->destroysubmatrices)(n, mat));
7152   } else {
7153     PetscCall(MatDestroyMatrices(n, mat));
7154   }
7155   PetscFunctionReturn(PETSC_SUCCESS);
7156 }
7157 
7158 /*@C
7159    MatGetSeqNonzeroStructure - Extracts the nonzero structure from a matrix and stores it, in its entirety, on each process
7160 
7161    Collective
7162 
7163    Input Parameter:
7164 .  mat - the matrix
7165 
7166    Output Parameter:
7167 .  matstruct - the sequential matrix with the nonzero structure of mat
7168 
7169   Level: developer
7170 
7171 .seealso: [](chapter_matrices), `Mat`, `MatDestroySeqNonzeroStructure()`, `MatCreateSubMatrices()`, `MatDestroyMatrices()`
7172 @*/
7173 PetscErrorCode MatGetSeqNonzeroStructure(Mat mat, Mat *matstruct)
7174 {
7175   PetscFunctionBegin;
7176   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7177   PetscValidPointer(matstruct, 2);
7178 
7179   PetscValidType(mat, 1);
7180   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7181   MatCheckPreallocated(mat, 1);
7182 
7183   PetscCall(PetscLogEventBegin(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7184   PetscUseTypeMethod(mat, getseqnonzerostructure, matstruct);
7185   PetscCall(PetscLogEventEnd(MAT_GetSeqNonzeroStructure, mat, 0, 0, 0));
7186   PetscFunctionReturn(PETSC_SUCCESS);
7187 }
7188 
7189 /*@C
7190    MatDestroySeqNonzeroStructure - Destroys matrix obtained with `MatGetSeqNonzeroStructure()`.
7191 
7192    Collective
7193 
7194    Input Parameter:
7195 .  mat - the matrix (this is a pointer to the array of matrices, just to match the calling
7196                        sequence of `MatGetSeqNonzeroStructure()`)
7197 
7198    Level: advanced
7199 
7200     Note:
7201     Frees not only the matrices, but also the array that contains the matrices
7202 
7203 .seealso: [](chapter_matrices), `Mat`, `MatGetSeqNonzeroStructure()`
7204 @*/
7205 PetscErrorCode MatDestroySeqNonzeroStructure(Mat *mat)
7206 {
7207   PetscFunctionBegin;
7208   PetscValidPointer(mat, 1);
7209   PetscCall(MatDestroy(mat));
7210   PetscFunctionReturn(PETSC_SUCCESS);
7211 }
7212 
7213 /*@
7214    MatIncreaseOverlap - Given a set of submatrices indicated by index sets,
7215    replaces the index sets by larger ones that represent submatrices with
7216    additional overlap.
7217 
7218    Collective
7219 
7220    Input Parameters:
7221 +  mat - the matrix
7222 .  n   - the number of index sets
7223 .  is  - the array of index sets (these index sets will changed during the call)
7224 -  ov  - the additional overlap requested
7225 
7226    Options Database Key:
7227 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7228 
7229    Level: developer
7230 
7231    Note:
7232    The computed overlap preserves the matrix block sizes when the blocks are square.
7233    That is: if a matrix nonzero for a given block would increase the overlap all columns associated with
7234    that block are included in the overlap regardless of whether each specific column would increase the overlap.
7235 
7236 .seealso: [](chapter_matrices), `Mat`, `PCASM`, `MatSetBlockSize()`, `MatIncreaseOverlapSplit()`, `MatCreateSubMatrices()`
7237 @*/
7238 PetscErrorCode MatIncreaseOverlap(Mat mat, PetscInt n, IS is[], PetscInt ov)
7239 {
7240   PetscInt i, bs, cbs;
7241 
7242   PetscFunctionBegin;
7243   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7244   PetscValidType(mat, 1);
7245   PetscValidLogicalCollectiveInt(mat, n, 2);
7246   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7247   if (n) {
7248     PetscValidPointer(is, 3);
7249     for (i = 0; i < n; i++) PetscValidHeaderSpecific(is[i], IS_CLASSID, 3);
7250   }
7251   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7252   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7253   MatCheckPreallocated(mat, 1);
7254 
7255   if (!ov || !n) PetscFunctionReturn(PETSC_SUCCESS);
7256   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7257   PetscUseTypeMethod(mat, increaseoverlap, n, is, ov);
7258   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7259   PetscCall(MatGetBlockSizes(mat, &bs, &cbs));
7260   if (bs == cbs) {
7261     for (i = 0; i < n; i++) PetscCall(ISSetBlockSize(is[i], bs));
7262   }
7263   PetscFunctionReturn(PETSC_SUCCESS);
7264 }
7265 
7266 PetscErrorCode MatIncreaseOverlapSplit_Single(Mat, IS *, PetscInt);
7267 
7268 /*@
7269    MatIncreaseOverlapSplit - Given a set of submatrices indicated by index sets across
7270    a sub communicator, replaces the index sets by larger ones that represent submatrices with
7271    additional overlap.
7272 
7273    Collective
7274 
7275    Input Parameters:
7276 +  mat - the matrix
7277 .  n   - the number of index sets
7278 .  is  - the array of index sets (these index sets will changed during the call)
7279 -  ov  - the additional overlap requested
7280 
7281 `   Options Database Key:
7282 .  -mat_increase_overlap_scalable - use a scalable algorithm to compute the overlap (supported by MPIAIJ matrix)
7283 
7284    Level: developer
7285 
7286 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatIncreaseOverlap()`
7287 @*/
7288 PetscErrorCode MatIncreaseOverlapSplit(Mat mat, PetscInt n, IS is[], PetscInt ov)
7289 {
7290   PetscInt i;
7291 
7292   PetscFunctionBegin;
7293   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7294   PetscValidType(mat, 1);
7295   PetscCheck(n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Must have one or more domains, you have %" PetscInt_FMT, n);
7296   if (n) {
7297     PetscValidPointer(is, 3);
7298     PetscValidHeaderSpecific(*is, IS_CLASSID, 3);
7299   }
7300   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
7301   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
7302   MatCheckPreallocated(mat, 1);
7303   if (!ov) PetscFunctionReturn(PETSC_SUCCESS);
7304   PetscCall(PetscLogEventBegin(MAT_IncreaseOverlap, mat, 0, 0, 0));
7305   for (i = 0; i < n; i++) PetscCall(MatIncreaseOverlapSplit_Single(mat, &is[i], ov));
7306   PetscCall(PetscLogEventEnd(MAT_IncreaseOverlap, mat, 0, 0, 0));
7307   PetscFunctionReturn(PETSC_SUCCESS);
7308 }
7309 
7310 /*@
7311    MatGetBlockSize - Returns the matrix block size.
7312 
7313    Not Collective
7314 
7315    Input Parameter:
7316 .  mat - the matrix
7317 
7318    Output Parameter:
7319 .  bs - block size
7320 
7321    Level: intermediate
7322 
7323    Notes:
7324     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7325 
7326    If the block size has not been set yet this routine returns 1.
7327 
7328 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSizes()`
7329 @*/
7330 PetscErrorCode MatGetBlockSize(Mat mat, PetscInt *bs)
7331 {
7332   PetscFunctionBegin;
7333   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7334   PetscValidIntPointer(bs, 2);
7335   *bs = PetscAbs(mat->rmap->bs);
7336   PetscFunctionReturn(PETSC_SUCCESS);
7337 }
7338 
7339 /*@
7340    MatGetBlockSizes - Returns the matrix block row and column sizes.
7341 
7342    Not Collective
7343 
7344    Input Parameter:
7345 .  mat - the matrix
7346 
7347    Output Parameters:
7348 +  rbs - row block size
7349 -  cbs - column block size
7350 
7351    Level: intermediate
7352 
7353    Notes:
7354     Block row formats are `MATBAIJ` and `MATSBAIJ` ALWAYS have square block storage in the matrix.
7355     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7356 
7357    If a block size has not been set yet this routine returns 1.
7358 
7359 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatSetBlockSizes()`
7360 @*/
7361 PetscErrorCode MatGetBlockSizes(Mat mat, PetscInt *rbs, PetscInt *cbs)
7362 {
7363   PetscFunctionBegin;
7364   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7365   if (rbs) PetscValidIntPointer(rbs, 2);
7366   if (cbs) PetscValidIntPointer(cbs, 3);
7367   if (rbs) *rbs = PetscAbs(mat->rmap->bs);
7368   if (cbs) *cbs = PetscAbs(mat->cmap->bs);
7369   PetscFunctionReturn(PETSC_SUCCESS);
7370 }
7371 
7372 /*@
7373    MatSetBlockSize - Sets the matrix block size.
7374 
7375    Logically Collective
7376 
7377    Input Parameters:
7378 +  mat - the matrix
7379 -  bs - block size
7380 
7381    Level: intermediate
7382 
7383    Notes:
7384     Block row formats are `MATBAIJ` and `MATSBAIJ` formats ALWAYS have square block storage in the matrix.
7385     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7386 
7387     For `MATAIJ` matrix format, this function can be called at a later stage, provided that the specified block size
7388     is compatible with the matrix local sizes.
7389 
7390 .seealso: [](chapter_matrices), `Mat`, `MATBAIJ`, `MATSBAIJ`, `MATAIJ`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`
7391 @*/
7392 PetscErrorCode MatSetBlockSize(Mat mat, PetscInt bs)
7393 {
7394   PetscFunctionBegin;
7395   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7396   PetscValidLogicalCollectiveInt(mat, bs, 2);
7397   PetscCall(MatSetBlockSizes(mat, bs, bs));
7398   PetscFunctionReturn(PETSC_SUCCESS);
7399 }
7400 
7401 typedef struct {
7402   PetscInt         n;
7403   IS              *is;
7404   Mat             *mat;
7405   PetscObjectState nonzerostate;
7406   Mat              C;
7407 } EnvelopeData;
7408 
7409 static PetscErrorCode EnvelopeDataDestroy(EnvelopeData *edata)
7410 {
7411   for (PetscInt i = 0; i < edata->n; i++) PetscCall(ISDestroy(&edata->is[i]));
7412   PetscCall(PetscFree(edata->is));
7413   PetscCall(PetscFree(edata));
7414   return PETSC_SUCCESS;
7415 }
7416 
7417 /*
7418    MatComputeVariableBlockEnvelope - Given a matrix whose nonzeros are in blocks along the diagonal this computes and stores
7419          the sizes of these blocks in the matrix. An individual block may lie over several processes.
7420 
7421    Collective
7422 
7423    Input Parameter:
7424 .  mat - the matrix
7425 
7426    Notes:
7427      There can be zeros within the blocks
7428 
7429      The blocks can overlap between processes, including laying on more than two processes
7430 
7431 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatSetVariableBlockSizes()`
7432 */
7433 static PetscErrorCode MatComputeVariableBlockEnvelope(Mat mat)
7434 {
7435   PetscInt           n, *sizes, *starts, i = 0, env = 0, tbs = 0, lblocks = 0, rstart, II, ln = 0, cnt = 0, cstart, cend;
7436   PetscInt          *diag, *odiag, sc;
7437   VecScatter         scatter;
7438   PetscScalar       *seqv;
7439   const PetscScalar *parv;
7440   const PetscInt    *ia, *ja;
7441   PetscBool          set, flag, done;
7442   Mat                AA = mat, A;
7443   MPI_Comm           comm;
7444   PetscMPIInt        rank, size, tag;
7445   MPI_Status         status;
7446   PetscContainer     container;
7447   EnvelopeData      *edata;
7448   Vec                seq, par;
7449   IS                 isglobal;
7450 
7451   PetscFunctionBegin;
7452   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7453   PetscCall(MatIsSymmetricKnown(mat, &set, &flag));
7454   if (!set || !flag) {
7455     /* TOO: only needs nonzero structure of transpose */
7456     PetscCall(MatTranspose(mat, MAT_INITIAL_MATRIX, &AA));
7457     PetscCall(MatAXPY(AA, 1.0, mat, DIFFERENT_NONZERO_PATTERN));
7458   }
7459   PetscCall(MatAIJGetLocalMat(AA, &A));
7460   PetscCall(MatGetRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7461   PetscCheck(done, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Unable to get IJ structure from matrix");
7462 
7463   PetscCall(MatGetLocalSize(mat, &n, NULL));
7464   PetscCall(PetscObjectGetNewTag((PetscObject)mat, &tag));
7465   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
7466   PetscCallMPI(MPI_Comm_size(comm, &size));
7467   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7468 
7469   PetscCall(PetscMalloc2(n, &sizes, n, &starts));
7470 
7471   if (rank > 0) {
7472     PetscCallMPI(MPI_Recv(&env, 1, MPIU_INT, rank - 1, tag, comm, &status));
7473     PetscCallMPI(MPI_Recv(&tbs, 1, MPIU_INT, rank - 1, tag, comm, &status));
7474   }
7475   PetscCall(MatGetOwnershipRange(mat, &rstart, NULL));
7476   for (i = 0; i < n; i++) {
7477     env = PetscMax(env, ja[ia[i + 1] - 1]);
7478     II  = rstart + i;
7479     if (env == II) {
7480       starts[lblocks]  = tbs;
7481       sizes[lblocks++] = 1 + II - tbs;
7482       tbs              = 1 + II;
7483     }
7484   }
7485   if (rank < size - 1) {
7486     PetscCallMPI(MPI_Send(&env, 1, MPIU_INT, rank + 1, tag, comm));
7487     PetscCallMPI(MPI_Send(&tbs, 1, MPIU_INT, rank + 1, tag, comm));
7488   }
7489 
7490   PetscCall(MatRestoreRowIJ(A, 0, PETSC_FALSE, PETSC_FALSE, &n, &ia, &ja, &done));
7491   if (!set || !flag) PetscCall(MatDestroy(&AA));
7492   PetscCall(MatDestroy(&A));
7493 
7494   PetscCall(PetscNew(&edata));
7495   PetscCall(MatGetNonzeroState(mat, &edata->nonzerostate));
7496   edata->n = lblocks;
7497   /* create IS needed for extracting blocks from the original matrix */
7498   PetscCall(PetscMalloc1(lblocks, &edata->is));
7499   for (PetscInt i = 0; i < lblocks; i++) PetscCall(ISCreateStride(PETSC_COMM_SELF, sizes[i], starts[i], 1, &edata->is[i]));
7500 
7501   /* Create the resulting inverse matrix structure with preallocation information */
7502   PetscCall(MatCreate(PetscObjectComm((PetscObject)mat), &edata->C));
7503   PetscCall(MatSetSizes(edata->C, mat->rmap->n, mat->cmap->n, mat->rmap->N, mat->cmap->N));
7504   PetscCall(MatSetBlockSizesFromMats(edata->C, mat, mat));
7505   PetscCall(MatSetType(edata->C, MATAIJ));
7506 
7507   /* Communicate the start and end of each row, from each block to the correct rank */
7508   /* TODO: Use PetscSF instead of VecScatter */
7509   for (PetscInt i = 0; i < lblocks; i++) ln += sizes[i];
7510   PetscCall(VecCreateSeq(PETSC_COMM_SELF, 2 * ln, &seq));
7511   PetscCall(VecGetArrayWrite(seq, &seqv));
7512   for (PetscInt i = 0; i < lblocks; i++) {
7513     for (PetscInt j = 0; j < sizes[i]; j++) {
7514       seqv[cnt]     = starts[i];
7515       seqv[cnt + 1] = starts[i] + sizes[i];
7516       cnt += 2;
7517     }
7518   }
7519   PetscCall(VecRestoreArrayWrite(seq, &seqv));
7520   PetscCallMPI(MPI_Scan(&cnt, &sc, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)mat)));
7521   sc -= cnt;
7522   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat), 2 * mat->rmap->n, 2 * mat->rmap->N, &par));
7523   PetscCall(ISCreateStride(PETSC_COMM_SELF, cnt, sc, 1, &isglobal));
7524   PetscCall(VecScatterCreate(seq, NULL, par, isglobal, &scatter));
7525   PetscCall(ISDestroy(&isglobal));
7526   PetscCall(VecScatterBegin(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7527   PetscCall(VecScatterEnd(scatter, seq, par, INSERT_VALUES, SCATTER_FORWARD));
7528   PetscCall(VecScatterDestroy(&scatter));
7529   PetscCall(VecDestroy(&seq));
7530   PetscCall(MatGetOwnershipRangeColumn(mat, &cstart, &cend));
7531   PetscCall(PetscMalloc2(mat->rmap->n, &diag, mat->rmap->n, &odiag));
7532   PetscCall(VecGetArrayRead(par, &parv));
7533   cnt = 0;
7534   PetscCall(MatGetSize(mat, NULL, &n));
7535   for (PetscInt i = 0; i < mat->rmap->n; i++) {
7536     PetscInt start, end, d = 0, od = 0;
7537 
7538     start = (PetscInt)PetscRealPart(parv[cnt]);
7539     end   = (PetscInt)PetscRealPart(parv[cnt + 1]);
7540     cnt += 2;
7541 
7542     if (start < cstart) {
7543       od += cstart - start + n - cend;
7544       d += cend - cstart;
7545     } else if (start < cend) {
7546       od += n - cend;
7547       d += cend - start;
7548     } else od += n - start;
7549     if (end <= cstart) {
7550       od -= cstart - end + n - cend;
7551       d -= cend - cstart;
7552     } else if (end < cend) {
7553       od -= n - cend;
7554       d -= cend - end;
7555     } else od -= n - end;
7556 
7557     odiag[i] = od;
7558     diag[i]  = d;
7559   }
7560   PetscCall(VecRestoreArrayRead(par, &parv));
7561   PetscCall(VecDestroy(&par));
7562   PetscCall(MatXAIJSetPreallocation(edata->C, mat->rmap->bs, diag, odiag, NULL, NULL));
7563   PetscCall(PetscFree2(diag, odiag));
7564   PetscCall(PetscFree2(sizes, starts));
7565 
7566   PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &container));
7567   PetscCall(PetscContainerSetPointer(container, edata));
7568   PetscCall(PetscContainerSetUserDestroy(container, (PetscErrorCode(*)(void *))EnvelopeDataDestroy));
7569   PetscCall(PetscObjectCompose((PetscObject)mat, "EnvelopeData", (PetscObject)container));
7570   PetscCall(PetscObjectDereference((PetscObject)container));
7571   PetscFunctionReturn(PETSC_SUCCESS);
7572 }
7573 
7574 /*@
7575   MatInvertVariableBlockEnvelope - set matrix C to be the inverted block diagonal of matrix A
7576 
7577   Collective
7578 
7579   Input Parameters:
7580 + A - the matrix
7581 - reuse - indicates if the `C` matrix was obtained from a previous call to this routine
7582 
7583   Output Parameter:
7584 . C - matrix with inverted block diagonal of `A`
7585 
7586   Level: advanced
7587 
7588   Note:
7589      For efficiency the matrix `A` should have all the nonzero entries clustered in smallish blocks along the diagonal.
7590 
7591 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatComputeBlockDiagonal()`
7592 @*/
7593 PetscErrorCode MatInvertVariableBlockEnvelope(Mat A, MatReuse reuse, Mat *C)
7594 {
7595   PetscContainer   container;
7596   EnvelopeData    *edata;
7597   PetscObjectState nonzerostate;
7598 
7599   PetscFunctionBegin;
7600   PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7601   if (!container) {
7602     PetscCall(MatComputeVariableBlockEnvelope(A));
7603     PetscCall(PetscObjectQuery((PetscObject)A, "EnvelopeData", (PetscObject *)&container));
7604   }
7605   PetscCall(PetscContainerGetPointer(container, (void **)&edata));
7606   PetscCall(MatGetNonzeroState(A, &nonzerostate));
7607   PetscCheck(nonzerostate <= edata->nonzerostate, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Cannot handle changes to matrix nonzero structure");
7608   PetscCheck(reuse != MAT_REUSE_MATRIX || *C == edata->C, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "C matrix must be the same as previously output");
7609 
7610   PetscCall(MatCreateSubMatrices(A, edata->n, edata->is, edata->is, MAT_INITIAL_MATRIX, &edata->mat));
7611   *C = edata->C;
7612 
7613   for (PetscInt i = 0; i < edata->n; i++) {
7614     Mat          D;
7615     PetscScalar *dvalues;
7616 
7617     PetscCall(MatConvert(edata->mat[i], MATSEQDENSE, MAT_INITIAL_MATRIX, &D));
7618     PetscCall(MatSetOption(*C, MAT_ROW_ORIENTED, PETSC_FALSE));
7619     PetscCall(MatSeqDenseInvert(D));
7620     PetscCall(MatDenseGetArray(D, &dvalues));
7621     PetscCall(MatSetValuesIS(*C, edata->is[i], edata->is[i], dvalues, INSERT_VALUES));
7622     PetscCall(MatDestroy(&D));
7623   }
7624   PetscCall(MatDestroySubMatrices(edata->n, &edata->mat));
7625   PetscCall(MatAssemblyBegin(*C, MAT_FINAL_ASSEMBLY));
7626   PetscCall(MatAssemblyEnd(*C, MAT_FINAL_ASSEMBLY));
7627   PetscFunctionReturn(PETSC_SUCCESS);
7628 }
7629 
7630 /*@
7631    MatSetVariableBlockSizes - Sets diagonal point-blocks of the matrix that need not be of the same size
7632 
7633    Logically Collective
7634 
7635    Input Parameters:
7636 +  mat - the matrix
7637 .  nblocks - the number of blocks on this process, each block can only exist on a single process
7638 -  bsizes - the block sizes
7639 
7640    Level: intermediate
7641 
7642    Notes:
7643     Currently used by `PCVPBJACOBI` for `MATAIJ` matrices
7644 
7645     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.
7646 
7647 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatGetVariableBlockSizes()`,
7648           `MatComputeVariableBlockEnvelope()`, `PCVPBJACOBI`
7649 @*/
7650 PetscErrorCode MatSetVariableBlockSizes(Mat mat, PetscInt nblocks, PetscInt *bsizes)
7651 {
7652   PetscInt i, ncnt = 0, nlocal;
7653 
7654   PetscFunctionBegin;
7655   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7656   PetscCheck(nblocks >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of local blocks must be great than or equal to zero");
7657   PetscCall(MatGetLocalSize(mat, &nlocal, NULL));
7658   for (i = 0; i < nblocks; i++) ncnt += bsizes[i];
7659   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);
7660   PetscCall(PetscFree(mat->bsizes));
7661   mat->nblocks = nblocks;
7662   PetscCall(PetscMalloc1(nblocks, &mat->bsizes));
7663   PetscCall(PetscArraycpy(mat->bsizes, bsizes, nblocks));
7664   PetscFunctionReturn(PETSC_SUCCESS);
7665 }
7666 
7667 /*@C
7668    MatGetVariableBlockSizes - Gets a diagonal blocks of the matrix that need not be of the same size
7669 
7670    Logically Collective; No Fortran Support
7671 
7672    Input Parameter:
7673 .  mat - the matrix
7674 
7675    Output Parameters:
7676 +  nblocks - the number of blocks on this process
7677 -  bsizes - the block sizes
7678 
7679    Level: intermediate
7680 
7681 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`, `MatGetBlockSizes()`, `MatSetVariableBlockSizes()`, `MatComputeVariableBlockEnvelope()`
7682 @*/
7683 PetscErrorCode MatGetVariableBlockSizes(Mat mat, PetscInt *nblocks, const PetscInt **bsizes)
7684 {
7685   PetscFunctionBegin;
7686   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7687   *nblocks = mat->nblocks;
7688   *bsizes  = mat->bsizes;
7689   PetscFunctionReturn(PETSC_SUCCESS);
7690 }
7691 
7692 /*@
7693    MatSetBlockSizes - Sets the matrix block row and column sizes.
7694 
7695    Logically Collective
7696 
7697    Input Parameters:
7698 +  mat - the matrix
7699 .  rbs - row block size
7700 -  cbs - column block size
7701 
7702    Level: intermediate
7703 
7704    Notes:
7705     Block row formats are `MATBAIJ` and  `MATSBAIJ`. These formats ALWAYS have square block storage in the matrix.
7706     If you pass a different block size for the columns than the rows, the row block size determines the square block storage.
7707     This must be called before `MatSetUp()` or MatXXXSetPreallocation() (or will default to 1) and the block size cannot be changed later.
7708 
7709     For `MATAIJ` matrix this function can be called at a later stage, provided that the specified block sizes
7710     are compatible with the matrix local sizes.
7711 
7712     The row and column block size determine the blocksize of the "row" and "column" vectors returned by `MatCreateVecs()`.
7713 
7714 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSize()`, `MatGetBlockSizes()`
7715 @*/
7716 PetscErrorCode MatSetBlockSizes(Mat mat, PetscInt rbs, PetscInt cbs)
7717 {
7718   PetscFunctionBegin;
7719   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7720   PetscValidLogicalCollectiveInt(mat, rbs, 2);
7721   PetscValidLogicalCollectiveInt(mat, cbs, 3);
7722   PetscTryTypeMethod(mat, setblocksizes, rbs, cbs);
7723   if (mat->rmap->refcnt) {
7724     ISLocalToGlobalMapping l2g  = NULL;
7725     PetscLayout            nmap = NULL;
7726 
7727     PetscCall(PetscLayoutDuplicate(mat->rmap, &nmap));
7728     if (mat->rmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->rmap->mapping, &l2g));
7729     PetscCall(PetscLayoutDestroy(&mat->rmap));
7730     mat->rmap          = nmap;
7731     mat->rmap->mapping = l2g;
7732   }
7733   if (mat->cmap->refcnt) {
7734     ISLocalToGlobalMapping l2g  = NULL;
7735     PetscLayout            nmap = NULL;
7736 
7737     PetscCall(PetscLayoutDuplicate(mat->cmap, &nmap));
7738     if (mat->cmap->mapping) PetscCall(ISLocalToGlobalMappingDuplicate(mat->cmap->mapping, &l2g));
7739     PetscCall(PetscLayoutDestroy(&mat->cmap));
7740     mat->cmap          = nmap;
7741     mat->cmap->mapping = l2g;
7742   }
7743   PetscCall(PetscLayoutSetBlockSize(mat->rmap, rbs));
7744   PetscCall(PetscLayoutSetBlockSize(mat->cmap, cbs));
7745   PetscFunctionReturn(PETSC_SUCCESS);
7746 }
7747 
7748 /*@
7749    MatSetBlockSizesFromMats - Sets the matrix block row and column sizes to match a pair of matrices
7750 
7751    Logically Collective
7752 
7753    Input Parameters:
7754 +  mat - the matrix
7755 .  fromRow - matrix from which to copy row block size
7756 -  fromCol - matrix from which to copy column block size (can be same as fromRow)
7757 
7758    Level: developer
7759 
7760 .seealso: [](chapter_matrices), `Mat`, `MatCreateSeqBAIJ()`, `MatCreateBAIJ()`, `MatGetBlockSize()`, `MatSetBlockSizes()`
7761 @*/
7762 PetscErrorCode MatSetBlockSizesFromMats(Mat mat, Mat fromRow, Mat fromCol)
7763 {
7764   PetscFunctionBegin;
7765   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7766   PetscValidHeaderSpecific(fromRow, MAT_CLASSID, 2);
7767   PetscValidHeaderSpecific(fromCol, MAT_CLASSID, 3);
7768   if (fromRow->rmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->rmap, fromRow->rmap->bs));
7769   if (fromCol->cmap->bs > 0) PetscCall(PetscLayoutSetBlockSize(mat->cmap, fromCol->cmap->bs));
7770   PetscFunctionReturn(PETSC_SUCCESS);
7771 }
7772 
7773 /*@
7774    MatResidual - Default routine to calculate the residual r = b - Ax
7775 
7776    Collective
7777 
7778    Input Parameters:
7779 +  mat - the matrix
7780 .  b   - the right-hand-side
7781 -  x   - the approximate solution
7782 
7783    Output Parameter:
7784 .  r - location to store the residual
7785 
7786    Level: developer
7787 
7788 .seealso: [](chapter_matrices), `Mat`, `MatMult()`, `MatMultAdd()`, `PCMGSetResidual()`
7789 @*/
7790 PetscErrorCode MatResidual(Mat mat, Vec b, Vec x, Vec r)
7791 {
7792   PetscFunctionBegin;
7793   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7794   PetscValidHeaderSpecific(b, VEC_CLASSID, 2);
7795   PetscValidHeaderSpecific(x, VEC_CLASSID, 3);
7796   PetscValidHeaderSpecific(r, VEC_CLASSID, 4);
7797   PetscValidType(mat, 1);
7798   MatCheckPreallocated(mat, 1);
7799   PetscCall(PetscLogEventBegin(MAT_Residual, mat, 0, 0, 0));
7800   if (!mat->ops->residual) {
7801     PetscCall(MatMult(mat, x, r));
7802     PetscCall(VecAYPX(r, -1.0, b));
7803   } else {
7804     PetscUseTypeMethod(mat, residual, b, x, r);
7805   }
7806   PetscCall(PetscLogEventEnd(MAT_Residual, mat, 0, 0, 0));
7807   PetscFunctionReturn(PETSC_SUCCESS);
7808 }
7809 
7810 /*MC
7811     MatGetRowIJF90 - Obtains the compressed row storage i and j indices for the local rows of a sparse matrix
7812 
7813     Synopsis:
7814     MatGetRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7815 
7816     Not Collective
7817 
7818     Input Parameters:
7819 +   A - the matrix
7820 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7821 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7822 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7823                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7824                  always used.
7825 
7826     Output Parameters:
7827 +   n - number of local rows in the (possibly compressed) matrix
7828 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7829 .   ja - the column indices
7830 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7831            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7832 
7833     Level: developer
7834 
7835     Note:
7836     Use  `MatRestoreRowIJF90()` when you no longer need access to the data
7837 
7838 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatRestoreRowIJF90()`
7839 M*/
7840 
7841 /*MC
7842     MatRestoreRowIJF90 - restores the compressed row storage i and j indices for the local rows of a sparse matrix obtained with `MatGetRowIJF90()`
7843 
7844     Synopsis:
7845     MatRestoreRowIJF90(Mat A, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt n, {PetscInt, pointer :: ia(:)}, {PetscInt, pointer :: ja(:)}, PetscBool done,integer ierr)
7846 
7847     Not Collective
7848 
7849     Input Parameters:
7850 +   A - the  matrix
7851 .   shift -  0 or 1 indicating we want the indices starting at 0 or 1
7852 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7853     inodecompressed - `PETSC_TRUE` or `PETSC_FALSE`  indicating if the nonzero structure of the
7854                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7855                  always used.
7856 .   n - number of local rows in the (possibly compressed) matrix
7857 .   ia - the row pointers; that is ia[0] = 0, ia[row] = ia[row-1] + number of elements in that row of the matrix
7858 .   ja - the column indices
7859 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7860            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7861 
7862     Level: developer
7863 
7864 .seealso: [](chapter_matrices), [](sec_fortranarrays), `Mat`, `MATMPIAIJ`, `MatGetRowIJ()`, `MatRestoreRowIJ()`, `MatGetRowIJF90()`
7865 M*/
7866 
7867 /*@C
7868     MatGetRowIJ - Returns the compressed row storage i and j indices for the local rows of a sparse matrix
7869 
7870    Collective
7871 
7872     Input Parameters:
7873 +   mat - 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`  indicating 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 
7880     Output Parameters:
7881 +   n - number of local rows in the (possibly compressed) matrix, use `NULL` if not needed
7882 .   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
7883 .   ja - the column indices, use `NULL` if not needed
7884 -   done - indicates if the routine actually worked and returned appropriate ia[] and ja[] arrays; callers
7885            are responsible for handling the case when done == `PETSC_FALSE` and ia and ja are not set
7886 
7887     Level: developer
7888 
7889     Notes:
7890     You CANNOT change any of the ia[] or ja[] values.
7891 
7892     Use `MatRestoreRowIJ()` when you are finished accessing the ia[] and ja[] values.
7893 
7894     Fortran Notes:
7895     Use
7896 .vb
7897     PetscInt, pointer :: ia(:),ja(:)
7898     call MatGetRowIJF90(mat,shift,symmetric,inodecompressed,n,ia,ja,done,ierr)
7899     ! Access the ith and jth entries via ia(i) and ja(j)
7900 .ve
7901    `MatGetRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatGetRowIJF90()`
7902 
7903 .seealso: [](chapter_matrices), `Mat`, `MATAIJ`, `MatGetRowIJF90()`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`, `MatSeqAIJGetArray()`
7904 @*/
7905 PetscErrorCode MatGetRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7906 {
7907   PetscFunctionBegin;
7908   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7909   PetscValidType(mat, 1);
7910   if (n) PetscValidIntPointer(n, 5);
7911   if (ia) PetscValidPointer(ia, 6);
7912   if (ja) PetscValidPointer(ja, 7);
7913   if (done) PetscValidBoolPointer(done, 8);
7914   MatCheckPreallocated(mat, 1);
7915   if (!mat->ops->getrowij && done) *done = PETSC_FALSE;
7916   else {
7917     if (done) *done = PETSC_TRUE;
7918     PetscCall(PetscLogEventBegin(MAT_GetRowIJ, mat, 0, 0, 0));
7919     PetscUseTypeMethod(mat, getrowij, shift, symmetric, inodecompressed, n, ia, ja, done);
7920     PetscCall(PetscLogEventEnd(MAT_GetRowIJ, mat, 0, 0, 0));
7921   }
7922   PetscFunctionReturn(PETSC_SUCCESS);
7923 }
7924 
7925 /*@C
7926     MatGetColumnIJ - Returns the compressed column storage i and j indices for sequential matrices.
7927 
7928     Collective
7929 
7930     Input Parameters:
7931 +   mat - the matrix
7932 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7933 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be
7934                 symmetrized
7935 .   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7936                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7937                  always used.
7938 .   n - number of columns in the (possibly compressed) matrix
7939 .   ia - the column pointers; that is ia[0] = 0, ia[col] = i[col-1] + number of elements in that col of the matrix
7940 -   ja - the row indices
7941 
7942     Output Parameter:
7943 .   done - `PETSC_TRUE` or `PETSC_FALSE`, indicating whether the values have been returned
7944 
7945     Level: developer
7946 
7947 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreColumnIJ()`
7948 @*/
7949 PetscErrorCode MatGetColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7950 {
7951   PetscFunctionBegin;
7952   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
7953   PetscValidType(mat, 1);
7954   PetscValidIntPointer(n, 5);
7955   if (ia) PetscValidPointer(ia, 6);
7956   if (ja) PetscValidPointer(ja, 7);
7957   PetscValidBoolPointer(done, 8);
7958   MatCheckPreallocated(mat, 1);
7959   if (!mat->ops->getcolumnij) *done = PETSC_FALSE;
7960   else {
7961     *done = PETSC_TRUE;
7962     PetscUseTypeMethod(mat, getcolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
7963   }
7964   PetscFunctionReturn(PETSC_SUCCESS);
7965 }
7966 
7967 /*@C
7968     MatRestoreRowIJ - Call after you are completed with the ia,ja indices obtained with `MatGetRowIJ()`.
7969 
7970     Collective
7971 
7972     Input Parameters:
7973 +   mat - the matrix
7974 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
7975 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
7976 .   inodecompressed -  `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
7977                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
7978                  always used.
7979 .   n - size of (possibly compressed) matrix
7980 .   ia - the row pointers
7981 -   ja - the column indices
7982 
7983     Output Parameter:
7984 .   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
7985 
7986     Level: developer
7987 
7988     Note:
7989     This routine zeros out `n`, `ia`, and `ja`. This is to prevent accidental
7990     us of the array after it has been restored. If you pass `NULL`, it will
7991     not zero the pointers.  Use of ia or ja after `MatRestoreRowIJ()` is invalid.
7992 
7993     Fortran Note:
7994    `MatRestoreRowIJ()` Fortran binding is deprecated (since PETSc 3.19), use `MatRestoreRowIJF90()`
7995 
7996 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatRestoreRowIJF90()`, `MatRestoreColumnIJ()`
7997 @*/
7998 PetscErrorCode MatRestoreRowIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
7999 {
8000   PetscFunctionBegin;
8001   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8002   PetscValidType(mat, 1);
8003   if (ia) PetscValidPointer(ia, 6);
8004   if (ja) PetscValidPointer(ja, 7);
8005   if (done) PetscValidBoolPointer(done, 8);
8006   MatCheckPreallocated(mat, 1);
8007 
8008   if (!mat->ops->restorerowij && done) *done = PETSC_FALSE;
8009   else {
8010     if (done) *done = PETSC_TRUE;
8011     PetscUseTypeMethod(mat, restorerowij, shift, symmetric, inodecompressed, n, ia, ja, done);
8012     if (n) *n = 0;
8013     if (ia) *ia = NULL;
8014     if (ja) *ja = NULL;
8015   }
8016   PetscFunctionReturn(PETSC_SUCCESS);
8017 }
8018 
8019 /*@C
8020     MatRestoreColumnIJ - Call after you are completed with the ia,ja indices obtained with `MatGetColumnIJ()`.
8021 
8022     Collective
8023 
8024     Input Parameters:
8025 +   mat - the matrix
8026 .   shift - 1 or zero indicating we want the indices starting at 0 or 1
8027 .   symmetric - `PETSC_TRUE` or `PETSC_FALSE` indicating the matrix data structure should be symmetrized
8028 -   inodecompressed - `PETSC_TRUE` or `PETSC_FALSE` indicating if the nonzero structure of the
8029                  inodes or the nonzero elements is wanted. For `MATBAIJ` matrices the compressed version is
8030                  always used.
8031 
8032     Output Parameters:
8033 +   n - size of (possibly compressed) matrix
8034 .   ia - the column pointers
8035 .   ja - the row indices
8036 -   done - `PETSC_TRUE` or `PETSC_FALSE` indicated that the values have been returned
8037 
8038     Level: developer
8039 
8040 .seealso: [](chapter_matrices), `Mat`, `MatGetColumnIJ()`, `MatRestoreRowIJ()`
8041 @*/
8042 PetscErrorCode MatRestoreColumnIJ(Mat mat, PetscInt shift, PetscBool symmetric, PetscBool inodecompressed, PetscInt *n, const PetscInt *ia[], const PetscInt *ja[], PetscBool *done)
8043 {
8044   PetscFunctionBegin;
8045   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8046   PetscValidType(mat, 1);
8047   if (ia) PetscValidPointer(ia, 6);
8048   if (ja) PetscValidPointer(ja, 7);
8049   PetscValidBoolPointer(done, 8);
8050   MatCheckPreallocated(mat, 1);
8051 
8052   if (!mat->ops->restorecolumnij) *done = PETSC_FALSE;
8053   else {
8054     *done = PETSC_TRUE;
8055     PetscUseTypeMethod(mat, restorecolumnij, shift, symmetric, inodecompressed, n, ia, ja, done);
8056     if (n) *n = 0;
8057     if (ia) *ia = NULL;
8058     if (ja) *ja = NULL;
8059   }
8060   PetscFunctionReturn(PETSC_SUCCESS);
8061 }
8062 
8063 /*@C
8064     MatColoringPatch -Used inside matrix coloring routines that use `MatGetRowIJ()` and/or `MatGetColumnIJ()`.
8065 
8066     Collective
8067 
8068     Input Parameters:
8069 +   mat - the matrix
8070 .   ncolors - maximum color value
8071 .   n   - number of entries in colorarray
8072 -   colorarray - array indicating color for each column
8073 
8074     Output Parameter:
8075 .   iscoloring - coloring generated using colorarray information
8076 
8077     Level: developer
8078 
8079 .seealso: [](chapter_matrices), `Mat`, `MatGetRowIJ()`, `MatGetColumnIJ()`
8080 @*/
8081 PetscErrorCode MatColoringPatch(Mat mat, PetscInt ncolors, PetscInt n, ISColoringValue colorarray[], ISColoring *iscoloring)
8082 {
8083   PetscFunctionBegin;
8084   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8085   PetscValidType(mat, 1);
8086   PetscValidIntPointer(colorarray, 4);
8087   PetscValidPointer(iscoloring, 5);
8088   MatCheckPreallocated(mat, 1);
8089 
8090   if (!mat->ops->coloringpatch) {
8091     PetscCall(ISColoringCreate(PetscObjectComm((PetscObject)mat), ncolors, n, colorarray, PETSC_OWN_POINTER, iscoloring));
8092   } else {
8093     PetscUseTypeMethod(mat, coloringpatch, ncolors, n, colorarray, iscoloring);
8094   }
8095   PetscFunctionReturn(PETSC_SUCCESS);
8096 }
8097 
8098 /*@
8099    MatSetUnfactored - Resets a factored matrix to be treated as unfactored.
8100 
8101    Logically Collective
8102 
8103    Input Parameter:
8104 .  mat - the factored matrix to be reset
8105 
8106    Level: developer
8107 
8108    Notes:
8109    This routine should be used only with factored matrices formed by in-place
8110    factorization via ILU(0) (or by in-place LU factorization for the `MATSEQDENSE`
8111    format).  This option can save memory, for example, when solving nonlinear
8112    systems with a matrix-free Newton-Krylov method and a matrix-based, in-place
8113    ILU(0) preconditioner.
8114 
8115    One can specify in-place ILU(0) factorization by calling
8116 .vb
8117      PCType(pc,PCILU);
8118      PCFactorSeUseInPlace(pc);
8119 .ve
8120    or by using the options -pc_type ilu -pc_factor_in_place
8121 
8122    In-place factorization ILU(0) can also be used as a local
8123    solver for the blocks within the block Jacobi or additive Schwarz
8124    methods (runtime option: -sub_pc_factor_in_place).  See Users-Manual: ch_pc
8125    for details on setting local solver options.
8126 
8127    Most users should employ the `KSP` interface for linear solvers
8128    instead of working directly with matrix algebra routines such as this.
8129    See, e.g., `KSPCreate()`.
8130 
8131 .seealso: [](chapter_matrices), `Mat`, `PCFactorSetUseInPlace()`, `PCFactorGetUseInPlace()`
8132 @*/
8133 PetscErrorCode MatSetUnfactored(Mat mat)
8134 {
8135   PetscFunctionBegin;
8136   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8137   PetscValidType(mat, 1);
8138   MatCheckPreallocated(mat, 1);
8139   mat->factortype = MAT_FACTOR_NONE;
8140   if (!mat->ops->setunfactored) PetscFunctionReturn(PETSC_SUCCESS);
8141   PetscUseTypeMethod(mat, setunfactored);
8142   PetscFunctionReturn(PETSC_SUCCESS);
8143 }
8144 
8145 /*MC
8146     MatDenseGetArrayF90 - Accesses a matrix array from Fortran
8147 
8148     Synopsis:
8149     MatDenseGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8150 
8151     Not Collective
8152 
8153     Input Parameter:
8154 .   x - matrix
8155 
8156     Output Parameters:
8157 +   xx_v - the Fortran pointer to the array
8158 -   ierr - error code
8159 
8160     Example of Usage:
8161 .vb
8162       PetscScalar, pointer xx_v(:,:)
8163       ....
8164       call MatDenseGetArrayF90(x,xx_v,ierr)
8165       a = xx_v(3)
8166       call MatDenseRestoreArrayF90(x,xx_v,ierr)
8167 .ve
8168 
8169     Level: advanced
8170 
8171 .seealso: [](chapter_matrices), `Mat`, `MatDenseRestoreArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJGetArrayF90()`
8172 M*/
8173 
8174 /*MC
8175     MatDenseRestoreArrayF90 - Restores a matrix array that has been
8176     accessed with `MatDenseGetArrayF90()`.
8177 
8178     Synopsis:
8179     MatDenseRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:,:)},integer ierr)
8180 
8181     Not Collective
8182 
8183     Input Parameters:
8184 +   x - matrix
8185 -   xx_v - the Fortran90 pointer to the array
8186 
8187     Output Parameter:
8188 .   ierr - error code
8189 
8190     Example of Usage:
8191 .vb
8192        PetscScalar, pointer xx_v(:,:)
8193        ....
8194        call MatDenseGetArrayF90(x,xx_v,ierr)
8195        a = xx_v(3)
8196        call MatDenseRestoreArrayF90(x,xx_v,ierr)
8197 .ve
8198 
8199     Level: advanced
8200 
8201 .seealso: [](chapter_matrices), `Mat`, `MatDenseGetArrayF90()`, `MatDenseGetArray()`, `MatDenseRestoreArray()`, `MatSeqAIJRestoreArrayF90()`
8202 M*/
8203 
8204 /*MC
8205     MatSeqAIJGetArrayF90 - Accesses a matrix array from Fortran.
8206 
8207     Synopsis:
8208     MatSeqAIJGetArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8209 
8210     Not Collective
8211 
8212     Input Parameter:
8213 .   x - matrix
8214 
8215     Output Parameters:
8216 +   xx_v - the Fortran pointer to the array
8217 -   ierr - error code
8218 
8219     Example of Usage:
8220 .vb
8221       PetscScalar, pointer xx_v(:)
8222       ....
8223       call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8224       a = xx_v(3)
8225       call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8226 .ve
8227 
8228     Level: advanced
8229 
8230 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJRestoreArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseGetArrayF90()`
8231 M*/
8232 
8233 /*MC
8234     MatSeqAIJRestoreArrayF90 - Restores a matrix array that has been
8235     accessed with `MatSeqAIJGetArrayF90()`.
8236 
8237     Synopsis:
8238     MatSeqAIJRestoreArrayF90(Mat x,{Scalar, pointer :: xx_v(:)},integer ierr)
8239 
8240     Not Collective
8241 
8242     Input Parameters:
8243 +   x - matrix
8244 -   xx_v - the Fortran90 pointer to the array
8245 
8246     Output Parameter:
8247 .   ierr - error code
8248 
8249     Example of Usage:
8250 .vb
8251        PetscScalar, pointer xx_v(:)
8252        ....
8253        call MatSeqAIJGetArrayF90(x,xx_v,ierr)
8254        a = xx_v(3)
8255        call MatSeqAIJRestoreArrayF90(x,xx_v,ierr)
8256 .ve
8257 
8258     Level: advanced
8259 
8260 .seealso: [](chapter_matrices), `Mat`, `MatSeqAIJGetArrayF90()`, `MatSeqAIJGetArray()`, `MatSeqAIJRestoreArray()`, `MatDenseRestoreArrayF90()`
8261 M*/
8262 
8263 /*@
8264     MatCreateSubMatrix - Gets a single submatrix on the same number of processors
8265                       as the original matrix.
8266 
8267     Collective
8268 
8269     Input Parameters:
8270 +   mat - the original matrix
8271 .   isrow - parallel `IS` containing the rows this processor should obtain
8272 .   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.
8273 -   cll - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
8274 
8275     Output Parameter:
8276 .   newmat - the new submatrix, of the same type as the original matrix
8277 
8278     Level: advanced
8279 
8280     Notes:
8281     The submatrix will be able to be multiplied with vectors using the same layout as `iscol`.
8282 
8283     Some matrix types place restrictions on the row and column indices, such
8284     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;
8285     for example, if the block size is 3 one cannot select the 0 and 2 rows without selecting the 1 row.
8286 
8287     The index sets may not have duplicate entries.
8288 
8289       The first time this is called you should use a cll of `MAT_INITIAL_MATRIX`,
8290    the `MatCreateSubMatrix()` routine will create the newmat for you. Any additional calls
8291    to this routine with a mat of the same nonzero structure and with a call of `MAT_REUSE_MATRIX`
8292    will reuse the matrix generated the first time.  You should call `MatDestroy()` on `newmat` when
8293    you are finished using it.
8294 
8295     The communicator of the newly obtained matrix is ALWAYS the same as the communicator of
8296     the input matrix.
8297 
8298     If `iscol` is `NULL` then all columns are obtained (not supported in Fortran).
8299 
8300    Example usage:
8301    Consider the following 8x8 matrix with 34 non-zero values, that is
8302    assembled across 3 processors. Let's assume that proc0 owns 3 rows,
8303    proc1 owns 3 rows, proc2 owns 2 rows. This division can be shown
8304    as follows
8305 .vb
8306             1  2  0  |  0  3  0  |  0  4
8307     Proc0   0  5  6  |  7  0  0  |  8  0
8308             9  0 10  | 11  0  0  | 12  0
8309     -------------------------------------
8310            13  0 14  | 15 16 17  |  0  0
8311     Proc1   0 18  0  | 19 20 21  |  0  0
8312             0  0  0  | 22 23  0  | 24  0
8313     -------------------------------------
8314     Proc2  25 26 27  |  0  0 28  | 29  0
8315            30  0  0  | 31 32 33  |  0 34
8316 .ve
8317 
8318     Suppose `isrow` = [0 1 | 4 | 6 7] and `iscol` = [1 2 | 3 4 5 | 6].  The resulting submatrix is
8319 
8320 .vb
8321             2  0  |  0  3  0  |  0
8322     Proc0   5  6  |  7  0  0  |  8
8323     -------------------------------
8324     Proc1  18  0  | 19 20 21  |  0
8325     -------------------------------
8326     Proc2  26 27  |  0  0 28  | 29
8327             0  0  | 31 32 33  |  0
8328 .ve
8329 
8330 .seealso: [](chapter_matrices), `Mat`, `MatCreateSubMatrices()`, `MatCreateSubMatricesMPI()`, `MatCreateSubMatrixVirtual()`, `MatSubMatrixVirtualUpdate()`
8331 @*/
8332 PetscErrorCode MatCreateSubMatrix(Mat mat, IS isrow, IS iscol, MatReuse cll, Mat *newmat)
8333 {
8334   PetscMPIInt size;
8335   Mat        *local;
8336   IS          iscoltmp;
8337   PetscBool   flg;
8338 
8339   PetscFunctionBegin;
8340   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8341   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
8342   if (iscol) PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
8343   PetscValidPointer(newmat, 5);
8344   if (cll == MAT_REUSE_MATRIX) PetscValidHeaderSpecific(*newmat, MAT_CLASSID, 5);
8345   PetscValidType(mat, 1);
8346   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8347   PetscCheck(cll != MAT_IGNORE_MATRIX, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Cannot use MAT_IGNORE_MATRIX");
8348 
8349   MatCheckPreallocated(mat, 1);
8350   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8351 
8352   if (!iscol || isrow == iscol) {
8353     PetscBool   stride;
8354     PetscMPIInt grabentirematrix = 0, grab;
8355     PetscCall(PetscObjectTypeCompare((PetscObject)isrow, ISSTRIDE, &stride));
8356     if (stride) {
8357       PetscInt first, step, n, rstart, rend;
8358       PetscCall(ISStrideGetInfo(isrow, &first, &step));
8359       if (step == 1) {
8360         PetscCall(MatGetOwnershipRange(mat, &rstart, &rend));
8361         if (rstart == first) {
8362           PetscCall(ISGetLocalSize(isrow, &n));
8363           if (n == rend - rstart) grabentirematrix = 1;
8364         }
8365       }
8366     }
8367     PetscCall(MPIU_Allreduce(&grabentirematrix, &grab, 1, MPI_INT, MPI_MIN, PetscObjectComm((PetscObject)mat)));
8368     if (grab) {
8369       PetscCall(PetscInfo(mat, "Getting entire matrix as submatrix\n"));
8370       if (cll == MAT_INITIAL_MATRIX) {
8371         *newmat = mat;
8372         PetscCall(PetscObjectReference((PetscObject)mat));
8373       }
8374       PetscFunctionReturn(PETSC_SUCCESS);
8375     }
8376   }
8377 
8378   if (!iscol) {
8379     PetscCall(ISCreateStride(PetscObjectComm((PetscObject)mat), mat->cmap->n, mat->cmap->rstart, 1, &iscoltmp));
8380   } else {
8381     iscoltmp = iscol;
8382   }
8383 
8384   /* if original matrix is on just one processor then use submatrix generated */
8385   if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1 && cll == MAT_REUSE_MATRIX) {
8386     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_REUSE_MATRIX, &newmat));
8387     goto setproperties;
8388   } else if (mat->ops->createsubmatrices && !mat->ops->createsubmatrix && size == 1) {
8389     PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscoltmp, MAT_INITIAL_MATRIX, &local));
8390     *newmat = *local;
8391     PetscCall(PetscFree(local));
8392     goto setproperties;
8393   } else if (!mat->ops->createsubmatrix) {
8394     /* Create a new matrix type that implements the operation using the full matrix */
8395     PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8396     switch (cll) {
8397     case MAT_INITIAL_MATRIX:
8398       PetscCall(MatCreateSubMatrixVirtual(mat, isrow, iscoltmp, newmat));
8399       break;
8400     case MAT_REUSE_MATRIX:
8401       PetscCall(MatSubMatrixVirtualUpdate(*newmat, mat, isrow, iscoltmp));
8402       break;
8403     default:
8404       SETERRQ(PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "Invalid MatReuse, must be either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX");
8405     }
8406     PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8407     goto setproperties;
8408   }
8409 
8410   PetscCall(PetscLogEventBegin(MAT_CreateSubMat, mat, 0, 0, 0));
8411   PetscUseTypeMethod(mat, createsubmatrix, isrow, iscoltmp, cll, newmat);
8412   PetscCall(PetscLogEventEnd(MAT_CreateSubMat, mat, 0, 0, 0));
8413 
8414 setproperties:
8415   PetscCall(ISEqualUnsorted(isrow, iscoltmp, &flg));
8416   if (flg) PetscCall(MatPropagateSymmetryOptions(mat, *newmat));
8417   if (!iscol) PetscCall(ISDestroy(&iscoltmp));
8418   if (*newmat && cll == MAT_INITIAL_MATRIX) PetscCall(PetscObjectStateIncrease((PetscObject)*newmat));
8419   PetscFunctionReturn(PETSC_SUCCESS);
8420 }
8421 
8422 /*@
8423    MatPropagateSymmetryOptions - Propagates symmetry options set on a matrix to another matrix
8424 
8425    Not Collective
8426 
8427    Input Parameters:
8428 +  A - the matrix we wish to propagate options from
8429 -  B - the matrix we wish to propagate options to
8430 
8431    Level: beginner
8432 
8433    Note:
8434    Propagates the options associated to `MAT_SYMMETRY_ETERNAL`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_HERMITIAN`, `MAT_SPD`, `MAT_SYMMETRIC`, and `MAT_STRUCTURAL_SYMMETRY_ETERNAL`
8435 
8436 .seealso: [](chapter_matrices), `Mat`, `MatSetOption()`, `MatIsSymmetricKnown()`, `MatIsSPDKnown()`, `MatIsHermitianKnown()`, MatIsStructurallySymmetricKnown()`
8437 @*/
8438 PetscErrorCode MatPropagateSymmetryOptions(Mat A, Mat B)
8439 {
8440   PetscFunctionBegin;
8441   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8442   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
8443   B->symmetry_eternal            = A->symmetry_eternal;
8444   B->structural_symmetry_eternal = A->structural_symmetry_eternal;
8445   B->symmetric                   = A->symmetric;
8446   B->structurally_symmetric      = A->structurally_symmetric;
8447   B->spd                         = A->spd;
8448   B->hermitian                   = A->hermitian;
8449   PetscFunctionReturn(PETSC_SUCCESS);
8450 }
8451 
8452 /*@
8453    MatStashSetInitialSize - sets the sizes of the matrix stash, that is
8454    used during the assembly process to store values that belong to
8455    other processors.
8456 
8457    Not Collective
8458 
8459    Input Parameters:
8460 +  mat   - the matrix
8461 .  size  - the initial size of the stash.
8462 -  bsize - the initial size of the block-stash(if used).
8463 
8464    Options Database Keys:
8465 +   -matstash_initial_size <size> or <size0,size1,...sizep-1>
8466 -   -matstash_block_initial_size <bsize>  or <bsize0,bsize1,...bsizep-1>
8467 
8468    Level: intermediate
8469 
8470    Notes:
8471      The block-stash is used for values set with `MatSetValuesBlocked()` while
8472      the stash is used for values set with `MatSetValues()`
8473 
8474      Run with the option -info and look for output of the form
8475      MatAssemblyBegin_MPIXXX:Stash has MM entries, uses nn mallocs.
8476      to determine the appropriate value, MM, to use for size and
8477      MatAssemblyBegin_MPIXXX:Block-Stash has BMM entries, uses nn mallocs.
8478      to determine the value, BMM to use for bsize
8479 
8480 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashGetInfo()`
8481 @*/
8482 PetscErrorCode MatStashSetInitialSize(Mat mat, PetscInt size, PetscInt bsize)
8483 {
8484   PetscFunctionBegin;
8485   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8486   PetscValidType(mat, 1);
8487   PetscCall(MatStashSetInitialSize_Private(&mat->stash, size));
8488   PetscCall(MatStashSetInitialSize_Private(&mat->bstash, bsize));
8489   PetscFunctionReturn(PETSC_SUCCESS);
8490 }
8491 
8492 /*@
8493    MatInterpolateAdd - w = y + A*x or A'*x depending on the shape of
8494      the matrix
8495 
8496    Neighbor-wise Collective
8497 
8498    Input Parameters:
8499 +  mat   - the matrix
8500 .  x - the vector to be multiplied by the interpolation operator
8501 -  y - the vector to be added to the result
8502 
8503    Output Parameter:
8504 .  w - the resulting vector
8505 
8506    Level: intermediate
8507 
8508    Notes:
8509     `w` may be the same vector as `y`.
8510 
8511     This allows one to use either the restriction or interpolation (its transpose)
8512     matrix to do the interpolation
8513 
8514 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8515 @*/
8516 PetscErrorCode MatInterpolateAdd(Mat A, Vec x, Vec y, Vec w)
8517 {
8518   PetscInt M, N, Ny;
8519 
8520   PetscFunctionBegin;
8521   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8522   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8523   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8524   PetscValidHeaderSpecific(w, VEC_CLASSID, 4);
8525   PetscCall(MatGetSize(A, &M, &N));
8526   PetscCall(VecGetSize(y, &Ny));
8527   if (M == Ny) {
8528     PetscCall(MatMultAdd(A, x, y, w));
8529   } else {
8530     PetscCall(MatMultTransposeAdd(A, x, y, w));
8531   }
8532   PetscFunctionReturn(PETSC_SUCCESS);
8533 }
8534 
8535 /*@
8536    MatInterpolate - y = A*x or A'*x depending on the shape of
8537      the matrix
8538 
8539    Neighbor-wise Collective
8540 
8541    Input Parameters:
8542 +  mat   - the matrix
8543 -  x - the vector to be interpolated
8544 
8545    Output Parameter:
8546 .  y - the resulting vector
8547 
8548    Level: intermediate
8549 
8550    Note:
8551     This allows one to use either the restriction or interpolation (its transpose)
8552     matrix to do the interpolation
8553 
8554 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatRestrict()`, `PCMG`
8555 @*/
8556 PetscErrorCode MatInterpolate(Mat A, Vec x, Vec y)
8557 {
8558   PetscInt M, N, Ny;
8559 
8560   PetscFunctionBegin;
8561   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8562   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8563   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8564   PetscCall(MatGetSize(A, &M, &N));
8565   PetscCall(VecGetSize(y, &Ny));
8566   if (M == Ny) {
8567     PetscCall(MatMult(A, x, y));
8568   } else {
8569     PetscCall(MatMultTranspose(A, x, y));
8570   }
8571   PetscFunctionReturn(PETSC_SUCCESS);
8572 }
8573 
8574 /*@
8575    MatRestrict - y = A*x or A'*x
8576 
8577    Neighbor-wise Collective
8578 
8579    Input Parameters:
8580 +  mat   - the matrix
8581 -  x - the vector to be restricted
8582 
8583    Output Parameter:
8584 .  y - the resulting vector
8585 
8586    Level: intermediate
8587 
8588    Note:
8589     This allows one to use either the restriction or interpolation (its transpose)
8590     matrix to do the restriction
8591 
8592 .seealso: [](chapter_matrices), `Mat`, `MatMultAdd()`, `MatMultTransposeAdd()`, `MatInterpolate()`, `PCMG`
8593 @*/
8594 PetscErrorCode MatRestrict(Mat A, Vec x, Vec y)
8595 {
8596   PetscInt M, N, Ny;
8597 
8598   PetscFunctionBegin;
8599   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8600   PetscValidHeaderSpecific(x, VEC_CLASSID, 2);
8601   PetscValidHeaderSpecific(y, VEC_CLASSID, 3);
8602   PetscCall(MatGetSize(A, &M, &N));
8603   PetscCall(VecGetSize(y, &Ny));
8604   if (M == Ny) {
8605     PetscCall(MatMult(A, x, y));
8606   } else {
8607     PetscCall(MatMultTranspose(A, x, y));
8608   }
8609   PetscFunctionReturn(PETSC_SUCCESS);
8610 }
8611 
8612 /*@
8613    MatMatInterpolateAdd - Y = W + A*X or W + A'*X
8614 
8615    Neighbor-wise Collective
8616 
8617    Input Parameters:
8618 +  mat   - the matrix
8619 .  x - the input dense matrix to be multiplied
8620 -  w - the input dense matrix to be added to the result
8621 
8622    Output Parameter:
8623 .  y - the output dense matrix
8624 
8625    Level: intermediate
8626 
8627    Note:
8628     This allows one to use either the restriction or interpolation (its transpose)
8629     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8630     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8631 
8632 .seealso: [](chapter_matrices), `Mat`, `MatInterpolateAdd()`, `MatMatInterpolate()`, `MatMatRestrict()`, `PCMG`
8633 @*/
8634 PetscErrorCode MatMatInterpolateAdd(Mat A, Mat x, Mat w, Mat *y)
8635 {
8636   PetscInt  M, N, Mx, Nx, Mo, My = 0, Ny = 0;
8637   PetscBool trans = PETSC_TRUE;
8638   MatReuse  reuse = MAT_INITIAL_MATRIX;
8639 
8640   PetscFunctionBegin;
8641   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
8642   PetscValidHeaderSpecific(x, MAT_CLASSID, 2);
8643   PetscValidType(x, 2);
8644   if (w) PetscValidHeaderSpecific(w, MAT_CLASSID, 3);
8645   if (*y) PetscValidHeaderSpecific(*y, MAT_CLASSID, 4);
8646   PetscCall(MatGetSize(A, &M, &N));
8647   PetscCall(MatGetSize(x, &Mx, &Nx));
8648   if (N == Mx) trans = PETSC_FALSE;
8649   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);
8650   Mo = trans ? N : M;
8651   if (*y) {
8652     PetscCall(MatGetSize(*y, &My, &Ny));
8653     if (Mo == My && Nx == Ny) {
8654       reuse = MAT_REUSE_MATRIX;
8655     } else {
8656       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);
8657       PetscCall(MatDestroy(y));
8658     }
8659   }
8660 
8661   if (w && *y == w) { /* this is to minimize changes in PCMG */
8662     PetscBool flg;
8663 
8664     PetscCall(PetscObjectQuery((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject *)&w));
8665     if (w) {
8666       PetscInt My, Ny, Mw, Nw;
8667 
8668       PetscCall(PetscObjectTypeCompare((PetscObject)*y, ((PetscObject)w)->type_name, &flg));
8669       PetscCall(MatGetSize(*y, &My, &Ny));
8670       PetscCall(MatGetSize(w, &Mw, &Nw));
8671       if (!flg || My != Mw || Ny != Nw) w = NULL;
8672     }
8673     if (!w) {
8674       PetscCall(MatDuplicate(*y, MAT_COPY_VALUES, &w));
8675       PetscCall(PetscObjectCompose((PetscObject)*y, "__MatMatIntAdd_w", (PetscObject)w));
8676       PetscCall(PetscObjectDereference((PetscObject)w));
8677     } else {
8678       PetscCall(MatCopy(*y, w, UNKNOWN_NONZERO_PATTERN));
8679     }
8680   }
8681   if (!trans) {
8682     PetscCall(MatMatMult(A, x, reuse, PETSC_DEFAULT, y));
8683   } else {
8684     PetscCall(MatTransposeMatMult(A, x, reuse, PETSC_DEFAULT, y));
8685   }
8686   if (w) PetscCall(MatAXPY(*y, 1.0, w, UNKNOWN_NONZERO_PATTERN));
8687   PetscFunctionReturn(PETSC_SUCCESS);
8688 }
8689 
8690 /*@
8691    MatMatInterpolate - Y = A*X or A'*X
8692 
8693    Neighbor-wise Collective
8694 
8695    Input Parameters:
8696 +  mat   - the matrix
8697 -  x - the input dense matrix
8698 
8699    Output Parameter:
8700 .  y - the output dense matrix
8701 
8702    Level: intermediate
8703 
8704    Note:
8705     This allows one to use either the restriction or interpolation (its transpose)
8706     matrix to do the interpolation. y matrix can be reused if already created with the proper sizes,
8707     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8708 
8709 .seealso: [](chapter_matrices), `Mat`, `MatInterpolate()`, `MatRestrict()`, `MatMatRestrict()`, `PCMG`
8710 @*/
8711 PetscErrorCode MatMatInterpolate(Mat A, Mat x, Mat *y)
8712 {
8713   PetscFunctionBegin;
8714   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8715   PetscFunctionReturn(PETSC_SUCCESS);
8716 }
8717 
8718 /*@
8719    MatMatRestrict - Y = A*X or A'*X
8720 
8721    Neighbor-wise Collective
8722 
8723    Input Parameters:
8724 +  mat   - the matrix
8725 -  x - the input dense matrix
8726 
8727    Output Parameter:
8728 .  y - the output dense matrix
8729 
8730    Level: intermediate
8731 
8732    Note:
8733     This allows one to use either the restriction or interpolation (its transpose)
8734     matrix to do the restriction. y matrix can be reused if already created with the proper sizes,
8735     otherwise it will be recreated. y must be initialized to `NULL` if not supplied.
8736 
8737 .seealso: [](chapter_matrices), `Mat`, `MatRestrict()`, `MatInterpolate()`, `MatMatInterpolate()`, `PCMG`
8738 @*/
8739 PetscErrorCode MatMatRestrict(Mat A, Mat x, Mat *y)
8740 {
8741   PetscFunctionBegin;
8742   PetscCall(MatMatInterpolateAdd(A, x, NULL, y));
8743   PetscFunctionReturn(PETSC_SUCCESS);
8744 }
8745 
8746 /*@
8747    MatGetNullSpace - retrieves the null space of a matrix.
8748 
8749    Logically Collective
8750 
8751    Input Parameters:
8752 +  mat - the matrix
8753 -  nullsp - the null space object
8754 
8755    Level: developer
8756 
8757 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetNullSpace()`, `MatNullSpace`
8758 @*/
8759 PetscErrorCode MatGetNullSpace(Mat mat, MatNullSpace *nullsp)
8760 {
8761   PetscFunctionBegin;
8762   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8763   PetscValidPointer(nullsp, 2);
8764   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->nullsp) ? mat->transnullsp : mat->nullsp;
8765   PetscFunctionReturn(PETSC_SUCCESS);
8766 }
8767 
8768 /*@
8769    MatSetNullSpace - attaches a null space to a matrix.
8770 
8771    Logically Collective
8772 
8773    Input Parameters:
8774 +  mat - the matrix
8775 -  nullsp - the null space object
8776 
8777    Level: advanced
8778 
8779    Notes:
8780       This null space is used by the `KSP` linear solvers to solve singular systems.
8781 
8782       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`
8783 
8784       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
8785       to zero but the linear system will still be solved in a least squares sense.
8786 
8787       The fundamental theorem of linear algebra (Gilbert Strang, Introduction to Applied Mathematics, page 72) states that
8788    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).
8789    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
8790    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
8791    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).
8792    This  \hat{b} can be obtained by calling MatNullSpaceRemove() with the null space of the transpose of the matrix.
8793 
8794     If the matrix is known to be symmetric because it is an `MATSBAIJ` matrix or one as called
8795     `MatSetOption`(mat,`MAT_SYMMETRIC` or possibly `MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`); this
8796     routine also automatically calls `MatSetTransposeNullSpace()`.
8797 
8798     The user should call `MatNullSpaceDestroy()`.
8799 
8800 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetTransposeNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`,
8801           `KSPSetPCSide()`
8802 @*/
8803 PetscErrorCode MatSetNullSpace(Mat mat, MatNullSpace nullsp)
8804 {
8805   PetscFunctionBegin;
8806   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8807   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8808   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8809   PetscCall(MatNullSpaceDestroy(&mat->nullsp));
8810   mat->nullsp = nullsp;
8811   if (mat->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetTransposeNullSpace(mat, nullsp));
8812   PetscFunctionReturn(PETSC_SUCCESS);
8813 }
8814 
8815 /*@
8816    MatGetTransposeNullSpace - retrieves the null space of the transpose of a matrix.
8817 
8818    Logically Collective
8819 
8820    Input Parameters:
8821 +  mat - the matrix
8822 -  nullsp - the null space object
8823 
8824    Level: developer
8825 
8826 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatSetTransposeNullSpace()`, `MatSetNullSpace()`, `MatGetNullSpace()`
8827 @*/
8828 PetscErrorCode MatGetTransposeNullSpace(Mat mat, MatNullSpace *nullsp)
8829 {
8830   PetscFunctionBegin;
8831   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8832   PetscValidType(mat, 1);
8833   PetscValidPointer(nullsp, 2);
8834   *nullsp = (mat->symmetric == PETSC_BOOL3_TRUE && !mat->transnullsp) ? mat->nullsp : mat->transnullsp;
8835   PetscFunctionReturn(PETSC_SUCCESS);
8836 }
8837 
8838 /*@
8839    MatSetTransposeNullSpace - attaches the null space of a transpose of a matrix to the matrix
8840 
8841    Logically Collective
8842 
8843    Input Parameters:
8844 +  mat - the matrix
8845 -  nullsp - the null space object
8846 
8847    Level: advanced
8848 
8849    Notes:
8850    This allows solving singular linear systems defined by the transpose of the matrix using `KSP` solvers with left preconditioning.
8851 
8852    See `MatSetNullSpace()`
8853 
8854 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatSetNullSpace()`, `MatGetTransposeNullSpace()`, `MatNullSpaceRemove()`, `KSPSetPCSide()`
8855 @*/
8856 PetscErrorCode MatSetTransposeNullSpace(Mat mat, MatNullSpace nullsp)
8857 {
8858   PetscFunctionBegin;
8859   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8860   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8861   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8862   PetscCall(MatNullSpaceDestroy(&mat->transnullsp));
8863   mat->transnullsp = nullsp;
8864   PetscFunctionReturn(PETSC_SUCCESS);
8865 }
8866 
8867 /*@
8868    MatSetNearNullSpace - attaches a null space to a matrix, which is often the null space (rigid body modes) of the operator without boundary conditions
8869         This null space will be used to provide near null space vectors to a multigrid preconditioner built from this matrix.
8870 
8871    Logically Collective
8872 
8873    Input Parameters:
8874 +  mat - the matrix
8875 -  nullsp - the null space object
8876 
8877    Level: advanced
8878 
8879    Notes:
8880    Overwrites any previous near null space that may have been attached
8881 
8882    You can remove the null space by calling this routine with an nullsp of `NULL`
8883 
8884 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatCreate()`, `MatNullSpaceCreate()`, `MatSetNullSpace()`, `MatNullSpaceCreateRigidBody()`, `MatGetNearNullSpace()`
8885 @*/
8886 PetscErrorCode MatSetNearNullSpace(Mat mat, MatNullSpace nullsp)
8887 {
8888   PetscFunctionBegin;
8889   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8890   PetscValidType(mat, 1);
8891   if (nullsp) PetscValidHeaderSpecific(nullsp, MAT_NULLSPACE_CLASSID, 2);
8892   MatCheckPreallocated(mat, 1);
8893   if (nullsp) PetscCall(PetscObjectReference((PetscObject)nullsp));
8894   PetscCall(MatNullSpaceDestroy(&mat->nearnullsp));
8895   mat->nearnullsp = nullsp;
8896   PetscFunctionReturn(PETSC_SUCCESS);
8897 }
8898 
8899 /*@
8900    MatGetNearNullSpace - Get null space attached with `MatSetNearNullSpace()`
8901 
8902    Not Collective
8903 
8904    Input Parameter:
8905 .  mat - the matrix
8906 
8907    Output Parameter:
8908 .  nullsp - the null space object, `NULL` if not set
8909 
8910    Level: advanced
8911 
8912 .seealso: [](chapter_matrices), `Mat`, `MatNullSpace`, `MatSetNearNullSpace()`, `MatGetNullSpace()`, `MatNullSpaceCreate()`
8913 @*/
8914 PetscErrorCode MatGetNearNullSpace(Mat mat, MatNullSpace *nullsp)
8915 {
8916   PetscFunctionBegin;
8917   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8918   PetscValidType(mat, 1);
8919   PetscValidPointer(nullsp, 2);
8920   MatCheckPreallocated(mat, 1);
8921   *nullsp = mat->nearnullsp;
8922   PetscFunctionReturn(PETSC_SUCCESS);
8923 }
8924 
8925 /*@C
8926    MatICCFactor - Performs in-place incomplete Cholesky factorization of matrix.
8927 
8928    Collective
8929 
8930    Input Parameters:
8931 +  mat - the matrix
8932 .  row - row/column permutation
8933 -  info - information on desired factorization process
8934 
8935    Level: developer
8936 
8937    Notes:
8938    Probably really in-place only when level of fill is zero, otherwise allocates
8939    new space to store factored matrix and deletes previous memory.
8940 
8941    Most users should employ the `KSP` interface for linear solvers
8942    instead of working directly with matrix algebra routines such as this.
8943    See, e.g., `KSPCreate()`.
8944 
8945    Developer Note:
8946    The Fortran interface is not autogenerated as the
8947    interface definition cannot be generated correctly [due to `MatFactorInfo`]
8948 
8949 .seealso: [](chapter_matrices), `Mat`, `MatFactorInfo`, `MatGetFactor()`, `MatICCFactorSymbolic()`, `MatLUFactorNumeric()`, `MatCholeskyFactor()`
8950 @*/
8951 PetscErrorCode MatICCFactor(Mat mat, IS row, const MatFactorInfo *info)
8952 {
8953   PetscFunctionBegin;
8954   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8955   PetscValidType(mat, 1);
8956   if (row) PetscValidHeaderSpecific(row, IS_CLASSID, 2);
8957   PetscValidPointer(info, 3);
8958   PetscCheck(mat->rmap->N == mat->cmap->N, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONG, "matrix must be square");
8959   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
8960   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
8961   MatCheckPreallocated(mat, 1);
8962   PetscUseTypeMethod(mat, iccfactor, row, info);
8963   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
8964   PetscFunctionReturn(PETSC_SUCCESS);
8965 }
8966 
8967 /*@
8968    MatDiagonalScaleLocal - Scales columns of a matrix given the scaling values including the
8969          ghosted ones.
8970 
8971    Not Collective
8972 
8973    Input Parameters:
8974 +  mat - the matrix
8975 -  diag - the diagonal values, including ghost ones
8976 
8977    Level: developer
8978 
8979    Notes:
8980     Works only for `MATMPIAIJ` and `MATMPIBAIJ` matrices
8981 
8982     This allows one to avoid during communication to perform the scaling that must be done with `MatDiagonalScale()`
8983 
8984 .seealso: [](chapter_matrices), `Mat`, `MatDiagonalScale()`
8985 @*/
8986 PetscErrorCode MatDiagonalScaleLocal(Mat mat, Vec diag)
8987 {
8988   PetscMPIInt size;
8989 
8990   PetscFunctionBegin;
8991   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
8992   PetscValidHeaderSpecific(diag, VEC_CLASSID, 2);
8993   PetscValidType(mat, 1);
8994 
8995   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must be already assembled");
8996   PetscCall(PetscLogEventBegin(MAT_Scale, mat, 0, 0, 0));
8997   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
8998   if (size == 1) {
8999     PetscInt n, m;
9000     PetscCall(VecGetSize(diag, &n));
9001     PetscCall(MatGetSize(mat, NULL, &m));
9002     PetscCheck(m == n, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only supported for sequential matrices when no ghost points/periodic conditions");
9003     PetscCall(MatDiagonalScale(mat, NULL, diag));
9004   } else {
9005     PetscUseMethod(mat, "MatDiagonalScaleLocal_C", (Mat, Vec), (mat, diag));
9006   }
9007   PetscCall(PetscLogEventEnd(MAT_Scale, mat, 0, 0, 0));
9008   PetscCall(PetscObjectStateIncrease((PetscObject)mat));
9009   PetscFunctionReturn(PETSC_SUCCESS);
9010 }
9011 
9012 /*@
9013    MatGetInertia - Gets the inertia from a factored matrix
9014 
9015    Collective
9016 
9017    Input Parameter:
9018 .  mat - the matrix
9019 
9020    Output Parameters:
9021 +   nneg - number of negative eigenvalues
9022 .   nzero - number of zero eigenvalues
9023 -   npos - number of positive eigenvalues
9024 
9025    Level: advanced
9026 
9027    Note:
9028     Matrix must have been factored by `MatCholeskyFactor()`
9029 
9030 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatCholeskyFactor()`
9031 @*/
9032 PetscErrorCode MatGetInertia(Mat mat, PetscInt *nneg, PetscInt *nzero, PetscInt *npos)
9033 {
9034   PetscFunctionBegin;
9035   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9036   PetscValidType(mat, 1);
9037   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9038   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Numeric factor mat is not assembled");
9039   PetscUseTypeMethod(mat, getinertia, nneg, nzero, npos);
9040   PetscFunctionReturn(PETSC_SUCCESS);
9041 }
9042 
9043 /*@C
9044    MatSolves - Solves A x = b, given a factored matrix, for a collection of vectors
9045 
9046    Neighbor-wise Collective
9047 
9048    Input Parameters:
9049 +  mat - the factored matrix obtained with `MatGetFactor()`
9050 -  b - the right-hand-side vectors
9051 
9052    Output Parameter:
9053 .  x - the result vectors
9054 
9055    Level: developer
9056 
9057    Note:
9058    The vectors `b` and `x` cannot be the same.  I.e., one cannot
9059    call `MatSolves`(A,x,x).
9060 
9061 .seealso: [](chapter_matrices), `Mat`, `Vecs`, `MatSolveAdd()`, `MatSolveTranspose()`, `MatSolveTransposeAdd()`, `MatSolve()`
9062 @*/
9063 PetscErrorCode MatSolves(Mat mat, Vecs b, Vecs x)
9064 {
9065   PetscFunctionBegin;
9066   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9067   PetscValidType(mat, 1);
9068   PetscCheck(x != b, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_IDN, "x and b must be different vectors");
9069   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Unfactored matrix");
9070   if (!mat->rmap->N && !mat->cmap->N) PetscFunctionReturn(PETSC_SUCCESS);
9071 
9072   MatCheckPreallocated(mat, 1);
9073   PetscCall(PetscLogEventBegin(MAT_Solves, mat, 0, 0, 0));
9074   PetscUseTypeMethod(mat, solves, b, x);
9075   PetscCall(PetscLogEventEnd(MAT_Solves, mat, 0, 0, 0));
9076   PetscFunctionReturn(PETSC_SUCCESS);
9077 }
9078 
9079 /*@
9080    MatIsSymmetric - Test whether a matrix is symmetric
9081 
9082    Collective
9083 
9084    Input Parameters:
9085 +  A - the matrix to test
9086 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact transpose)
9087 
9088    Output Parameter:
9089 .  flg - the result
9090 
9091    Level: intermediate
9092 
9093    Notes:
9094     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9095 
9096     If the matrix does not yet know if it is symmetric or not this can be an expensive operation, also available `MatIsSymmetricKnown()`
9097 
9098     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9099     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9100 
9101 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetricKnown()`,
9102           `MAT_SYMMETRIC`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9103 @*/
9104 PetscErrorCode MatIsSymmetric(Mat A, PetscReal tol, PetscBool *flg)
9105 {
9106   PetscFunctionBegin;
9107   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9108   PetscValidBoolPointer(flg, 3);
9109 
9110   if (A->symmetric == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9111   else if (A->symmetric == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9112   else {
9113     PetscUseTypeMethod(A, issymmetric, tol, flg);
9114     if (!tol) PetscCall(MatSetOption(A, MAT_SYMMETRIC, *flg));
9115   }
9116   PetscFunctionReturn(PETSC_SUCCESS);
9117 }
9118 
9119 /*@
9120    MatIsHermitian - Test whether a matrix is Hermitian
9121 
9122    Collective
9123 
9124    Input Parameters:
9125 +  A - the matrix to test
9126 -  tol - difference between value and its transpose less than this amount counts as equal (use 0.0 for exact Hermitian)
9127 
9128    Output Parameter:
9129 .  flg - the result
9130 
9131    Level: intermediate
9132 
9133    Notes:
9134     For real numbers `MatIsSymmetric()` and `MatIsHermitian()` return identical results
9135 
9136     If the matrix does not yet know if it is Hermitian or not this can be an expensive operation, also available `MatIsHermitianKnown()`
9137 
9138     One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9139     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMEMTRY_ETERNAL`,`PETSC_TRUE`)
9140 
9141 .seealso: [](chapter_matrices), `Mat`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitianKnown()`, `MatIsStructurallySymmetric()`, `MatSetOption()`,
9142           `MatIsSymmetricKnown()`, `MatIsSymmetric()`, `MAT_HERMITIAN`, `MAT_SYMMETRY_ETERNAL`, `MatSetOption()`
9143 @*/
9144 PetscErrorCode MatIsHermitian(Mat A, PetscReal tol, PetscBool *flg)
9145 {
9146   PetscFunctionBegin;
9147   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9148   PetscValidBoolPointer(flg, 3);
9149 
9150   if (A->hermitian == PETSC_BOOL3_TRUE) *flg = PETSC_TRUE;
9151   else if (A->hermitian == PETSC_BOOL3_FALSE) *flg = PETSC_FALSE;
9152   else {
9153     PetscUseTypeMethod(A, ishermitian, tol, flg);
9154     if (!tol) PetscCall(MatSetOption(A, MAT_HERMITIAN, *flg));
9155   }
9156   PetscFunctionReturn(PETSC_SUCCESS);
9157 }
9158 
9159 /*@
9160    MatIsSymmetricKnown - Checks if a matrix knows if it is symmetric or not and its symmetric state
9161 
9162    Not Collective
9163 
9164    Input Parameter:
9165 .  A - the matrix to check
9166 
9167    Output Parameters:
9168 +  set - `PETSC_TRUE` if the matrix knows its symmetry state (this tells you if the next flag is valid)
9169 -  flg - the result (only valid if set is `PETSC_TRUE`)
9170 
9171    Level: advanced
9172 
9173    Notes:
9174    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsSymmetric()`
9175    if you want it explicitly checked
9176 
9177     One can declare that a matrix is symmetric with `MatSetOption`(mat,`MAT_SYMMETRIC`,`PETSC_TRUE`) and if it is known to remain symmetric
9178     after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9179 
9180 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9181 @*/
9182 PetscErrorCode MatIsSymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9183 {
9184   PetscFunctionBegin;
9185   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9186   PetscValidBoolPointer(set, 2);
9187   PetscValidBoolPointer(flg, 3);
9188   if (A->symmetric != PETSC_BOOL3_UNKNOWN) {
9189     *set = PETSC_TRUE;
9190     *flg = PetscBool3ToBool(A->symmetric);
9191   } else {
9192     *set = PETSC_FALSE;
9193   }
9194   PetscFunctionReturn(PETSC_SUCCESS);
9195 }
9196 
9197 /*@
9198    MatIsSPDKnown - Checks if a matrix knows if it is symmetric positive definite or not and its symmetric positive definite state
9199 
9200    Not Collective
9201 
9202    Input Parameter:
9203 .  A - the matrix to check
9204 
9205    Output Parameters:
9206 +  set - `PETSC_TRUE` if the matrix knows its symmetric positive definite state (this tells you if the next flag is valid)
9207 -  flg - the result (only valid if set is `PETSC_TRUE`)
9208 
9209    Level: advanced
9210 
9211    Notes:
9212    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`).
9213 
9214    One can declare that a matrix is SPD with `MatSetOption`(mat,`MAT_SPD`,`PETSC_TRUE`) and if it is known to remain SPD
9215    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SPD_ETERNAL`,`PETSC_TRUE`)
9216 
9217 .seealso: [](chapter_matrices), `Mat`, `MAT_SPD_ETERNAL`, `MAT_SPD`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9218 @*/
9219 PetscErrorCode MatIsSPDKnown(Mat A, PetscBool *set, PetscBool *flg)
9220 {
9221   PetscFunctionBegin;
9222   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9223   PetscValidBoolPointer(set, 2);
9224   PetscValidBoolPointer(flg, 3);
9225   if (A->spd != PETSC_BOOL3_UNKNOWN) {
9226     *set = PETSC_TRUE;
9227     *flg = PetscBool3ToBool(A->spd);
9228   } else {
9229     *set = PETSC_FALSE;
9230   }
9231   PetscFunctionReturn(PETSC_SUCCESS);
9232 }
9233 
9234 /*@
9235    MatIsHermitianKnown - Checks if a matrix knows if it is Hermitian or not and its Hermitian state
9236 
9237    Not Collective
9238 
9239    Input Parameter:
9240 .  A - the matrix to check
9241 
9242    Output Parameters:
9243 +  set - `PETSC_TRUE` if the matrix knows its Hermitian state (this tells you if the next flag is valid)
9244 -  flg - the result (only valid if set is `PETSC_TRUE`)
9245 
9246    Level: advanced
9247 
9248    Notes:
9249    Does not check the matrix values directly, so this may return unknown (set = `PETSC_FALSE`). Use `MatIsHermitian()`
9250    if you want it explicitly checked
9251 
9252    One can declare that a matrix is Hermitian with `MatSetOption`(mat,`MAT_HERMITIAN`,`PETSC_TRUE`) and if it is known to remain Hermitian
9253    after changes to the matrices values one can call `MatSetOption`(mat,`MAT_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9254 
9255 .seealso: [](chapter_matrices), `Mat`, `MAT_SYMMETRY_ETERNAL`, `MAT_HERMITIAN`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`
9256 @*/
9257 PetscErrorCode MatIsHermitianKnown(Mat A, PetscBool *set, PetscBool *flg)
9258 {
9259   PetscFunctionBegin;
9260   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9261   PetscValidBoolPointer(set, 2);
9262   PetscValidBoolPointer(flg, 3);
9263   if (A->hermitian != PETSC_BOOL3_UNKNOWN) {
9264     *set = PETSC_TRUE;
9265     *flg = PetscBool3ToBool(A->hermitian);
9266   } else {
9267     *set = PETSC_FALSE;
9268   }
9269   PetscFunctionReturn(PETSC_SUCCESS);
9270 }
9271 
9272 /*@
9273    MatIsStructurallySymmetric - Test whether a matrix is structurally symmetric
9274 
9275    Collective
9276 
9277    Input Parameter:
9278 .  A - the matrix to test
9279 
9280    Output Parameter:
9281 .  flg - the result
9282 
9283    Level: intermediate
9284 
9285    Notes:
9286    If the matrix does yet know it is structurally symmetric this can be an expensive operation, also available `MatIsStructurallySymmetricKnown()`
9287 
9288    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
9289    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9290 
9291 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MAT_STRUCTURAL_SYMMETRY_ETERNAL`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsSymmetric()`, `MatSetOption()`, `MatIsStructurallySymmetricKnown()`
9292 @*/
9293 PetscErrorCode MatIsStructurallySymmetric(Mat A, PetscBool *flg)
9294 {
9295   PetscFunctionBegin;
9296   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9297   PetscValidBoolPointer(flg, 2);
9298   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9299     *flg = PetscBool3ToBool(A->structurally_symmetric);
9300   } else {
9301     PetscUseTypeMethod(A, isstructurallysymmetric, flg);
9302     PetscCall(MatSetOption(A, MAT_STRUCTURALLY_SYMMETRIC, *flg));
9303   }
9304   PetscFunctionReturn(PETSC_SUCCESS);
9305 }
9306 
9307 /*@
9308    MatIsStructurallySymmetricKnown - Checks if a matrix knows if it is structurally symmetric or not and its structurally symmetric state
9309 
9310    Not Collective
9311 
9312    Input Parameter:
9313 .  A - the matrix to check
9314 
9315    Output Parameters:
9316 +  set - PETSC_TRUE if the matrix knows its structurally symmetric state (this tells you if the next flag is valid)
9317 -  flg - the result (only valid if set is PETSC_TRUE)
9318 
9319    Level: advanced
9320 
9321    Notes:
9322    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
9323    symmetric after changes to the matrices values one can call `MatSetOption`(mat,`MAT_STRUCTURAL_SYMMETRY_ETERNAL`,`PETSC_TRUE`)
9324 
9325    Use `MatIsStructurallySymmetric()` to explicitly check if a matrix is structurally symmetric (this is an expensive operation)
9326 
9327 .seealso: [](chapter_matrices), `Mat`, `MAT_STRUCTURALLY_SYMMETRIC`, `MatTranspose()`, `MatIsTranspose()`, `MatIsHermitian()`, `MatIsStructurallySymmetric()`, `MatSetOption()`, `MatIsSymmetric()`, `MatIsHermitianKnown()`
9328 @*/
9329 PetscErrorCode MatIsStructurallySymmetricKnown(Mat A, PetscBool *set, PetscBool *flg)
9330 {
9331   PetscFunctionBegin;
9332   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
9333   PetscValidBoolPointer(set, 2);
9334   PetscValidBoolPointer(flg, 3);
9335   if (A->structurally_symmetric != PETSC_BOOL3_UNKNOWN) {
9336     *set = PETSC_TRUE;
9337     *flg = PetscBool3ToBool(A->structurally_symmetric);
9338   } else {
9339     *set = PETSC_FALSE;
9340   }
9341   PetscFunctionReturn(PETSC_SUCCESS);
9342 }
9343 
9344 /*@
9345    MatStashGetInfo - Gets how many values are currently in the matrix stash, i.e. need
9346        to be communicated to other processors during the `MatAssemblyBegin()`/`MatAssemblyEnd()` process
9347 
9348     Not Collective
9349 
9350    Input Parameter:
9351 .   mat - the matrix
9352 
9353    Output Parameters:
9354 +   nstash   - the size of the stash
9355 .   reallocs - the number of additional mallocs incurred.
9356 .   bnstash   - the size of the block stash
9357 -   breallocs - the number of additional mallocs incurred.in the block stash
9358 
9359    Level: advanced
9360 
9361 .seealso: [](chapter_matrices), `MatAssemblyBegin()`, `MatAssemblyEnd()`, `Mat`, `MatStashSetInitialSize()`
9362 @*/
9363 PetscErrorCode MatStashGetInfo(Mat mat, PetscInt *nstash, PetscInt *reallocs, PetscInt *bnstash, PetscInt *breallocs)
9364 {
9365   PetscFunctionBegin;
9366   PetscCall(MatStashGetInfo_Private(&mat->stash, nstash, reallocs));
9367   PetscCall(MatStashGetInfo_Private(&mat->bstash, bnstash, breallocs));
9368   PetscFunctionReturn(PETSC_SUCCESS);
9369 }
9370 
9371 /*@C
9372    MatCreateVecs - Get vector(s) compatible with the matrix, i.e. with the same
9373    parallel layout, `PetscLayout` for rows and columns
9374 
9375    Collective
9376 
9377    Input Parameter:
9378 .  mat - the matrix
9379 
9380    Output Parameters:
9381 +   right - (optional) vector that the matrix can be multiplied against
9382 -   left - (optional) vector that the matrix vector product can be stored in
9383 
9384   Level: advanced
9385 
9386    Notes:
9387     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()`.
9388 
9389     These are new vectors which are not owned by the mat, they should be destroyed in `VecDestroy()` when no longer needed
9390 
9391 .seealso: [](chapter_matrices), `Mat`, `Vec`, `VecCreate()`, `VecDestroy()`, `DMCreateGlobalVector()`
9392 @*/
9393 PetscErrorCode MatCreateVecs(Mat mat, Vec *right, Vec *left)
9394 {
9395   PetscFunctionBegin;
9396   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9397   PetscValidType(mat, 1);
9398   if (mat->ops->getvecs) {
9399     PetscUseTypeMethod(mat, getvecs, right, left);
9400   } else {
9401     PetscInt rbs, cbs;
9402     PetscCall(MatGetBlockSizes(mat, &rbs, &cbs));
9403     if (right) {
9404       PetscCheck(mat->cmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for columns not yet setup");
9405       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), right));
9406       PetscCall(VecSetSizes(*right, mat->cmap->n, PETSC_DETERMINE));
9407       PetscCall(VecSetBlockSize(*right, cbs));
9408       PetscCall(VecSetType(*right, mat->defaultvectype));
9409 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9410       if (mat->boundtocpu && mat->bindingpropagates) {
9411         PetscCall(VecSetBindingPropagates(*right, PETSC_TRUE));
9412         PetscCall(VecBindToCPU(*right, PETSC_TRUE));
9413       }
9414 #endif
9415       PetscCall(PetscLayoutReference(mat->cmap, &(*right)->map));
9416     }
9417     if (left) {
9418       PetscCheck(mat->rmap->n >= 0, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "PetscLayout for rows not yet setup");
9419       PetscCall(VecCreate(PetscObjectComm((PetscObject)mat), left));
9420       PetscCall(VecSetSizes(*left, mat->rmap->n, PETSC_DETERMINE));
9421       PetscCall(VecSetBlockSize(*left, rbs));
9422       PetscCall(VecSetType(*left, mat->defaultvectype));
9423 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
9424       if (mat->boundtocpu && mat->bindingpropagates) {
9425         PetscCall(VecSetBindingPropagates(*left, PETSC_TRUE));
9426         PetscCall(VecBindToCPU(*left, PETSC_TRUE));
9427       }
9428 #endif
9429       PetscCall(PetscLayoutReference(mat->rmap, &(*left)->map));
9430     }
9431   }
9432   PetscFunctionReturn(PETSC_SUCCESS);
9433 }
9434 
9435 /*@C
9436    MatFactorInfoInitialize - Initializes a `MatFactorInfo` data structure
9437      with default values.
9438 
9439    Not Collective
9440 
9441    Input Parameter:
9442 .    info - the `MatFactorInfo` data structure
9443 
9444    Level: developer
9445 
9446    Notes:
9447     The solvers are generally used through the `KSP` and `PC` objects, for example
9448           `PCLU`, `PCILU`, `PCCHOLESKY`, `PCICC`
9449 
9450     Once the data structure is initialized one may change certain entries as desired for the particular factorization to be performed
9451 
9452    Developer Note:
9453    The Fortran interface is not autogenerated as the
9454    interface definition cannot be generated correctly [due to `MatFactorInfo`]
9455 
9456 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorInfo`
9457 @*/
9458 PetscErrorCode MatFactorInfoInitialize(MatFactorInfo *info)
9459 {
9460   PetscFunctionBegin;
9461   PetscCall(PetscMemzero(info, sizeof(MatFactorInfo)));
9462   PetscFunctionReturn(PETSC_SUCCESS);
9463 }
9464 
9465 /*@
9466    MatFactorSetSchurIS - Set indices corresponding to the Schur complement you wish to have computed
9467 
9468    Collective
9469 
9470    Input Parameters:
9471 +  mat - the factored matrix
9472 -  is - the index set defining the Schur indices (0-based)
9473 
9474    Level: advanced
9475 
9476    Notes:
9477     Call `MatFactorSolveSchurComplement()` or `MatFactorSolveSchurComplementTranspose()` after this call to solve a Schur complement system.
9478 
9479    You can call `MatFactorGetSchurComplement()` or `MatFactorCreateSchurComplement()` after this call.
9480 
9481    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9482 
9483 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorGetSchurComplement()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSolveSchurComplement()`,
9484           `MatFactorSolveSchurComplementTranspose()`, `MatFactorSolveSchurComplement()`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9485 @*/
9486 PetscErrorCode MatFactorSetSchurIS(Mat mat, IS is)
9487 {
9488   PetscErrorCode (*f)(Mat, IS);
9489 
9490   PetscFunctionBegin;
9491   PetscValidType(mat, 1);
9492   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
9493   PetscValidType(is, 2);
9494   PetscValidHeaderSpecific(is, IS_CLASSID, 2);
9495   PetscCheckSameComm(mat, 1, is, 2);
9496   PetscCheck(mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Only for factored matrix");
9497   PetscCall(PetscObjectQueryFunction((PetscObject)mat, "MatFactorSetSchurIS_C", &f));
9498   PetscCheck(f, PetscObjectComm((PetscObject)mat), PETSC_ERR_SUP, "The selected MatSolverType does not support Schur complement computation. You should use MATSOLVERMUMPS or MATSOLVERMKL_PARDISO");
9499   PetscCall(MatDestroy(&mat->schur));
9500   PetscCall((*f)(mat, is));
9501   PetscCheck(mat->schur, PetscObjectComm((PetscObject)mat), PETSC_ERR_PLIB, "Schur complement has not been created");
9502   PetscFunctionReturn(PETSC_SUCCESS);
9503 }
9504 
9505 /*@
9506   MatFactorCreateSchurComplement - Create a Schur complement matrix object using Schur data computed during the factorization step
9507 
9508    Logically Collective
9509 
9510    Input Parameters:
9511 +  F - the factored matrix obtained by calling `MatGetFactor()`
9512 .  S - location where to return the Schur complement, can be `NULL`
9513 -  status - the status of the Schur complement matrix, can be `NULL`
9514 
9515    Level: advanced
9516 
9517    Notes:
9518    You must call `MatFactorSetSchurIS()` before calling this routine.
9519 
9520    This functionality is only supported for `MATSOLVERMUMPS` and `MATSOLVERMKL_PARDISO`
9521 
9522    The routine provides a copy of the Schur matrix stored within the solver data structures.
9523    The caller must destroy the object when it is no longer needed.
9524    If `MatFactorInvertSchurComplement()` has been called, the routine gets back the inverse.
9525 
9526    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)
9527 
9528    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9529 
9530    Developer Note:
9531     The reason this routine exists is because the representation of the Schur complement within the factor matrix may be different than a standard PETSc
9532    matrix representation and we normally do not want to use the time or memory to make a copy as a regular PETSc matrix.
9533 
9534 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorSchurStatus`, `MATSOLVERMUMPS`, `MATSOLVERMKL_PARDISO`
9535 @*/
9536 PetscErrorCode MatFactorCreateSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9537 {
9538   PetscFunctionBegin;
9539   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9540   if (S) PetscValidPointer(S, 2);
9541   if (status) PetscValidPointer(status, 3);
9542   if (S) {
9543     PetscErrorCode (*f)(Mat, Mat *);
9544 
9545     PetscCall(PetscObjectQueryFunction((PetscObject)F, "MatFactorCreateSchurComplement_C", &f));
9546     if (f) {
9547       PetscCall((*f)(F, S));
9548     } else {
9549       PetscCall(MatDuplicate(F->schur, MAT_COPY_VALUES, S));
9550     }
9551   }
9552   if (status) *status = F->schur_status;
9553   PetscFunctionReturn(PETSC_SUCCESS);
9554 }
9555 
9556 /*@
9557   MatFactorGetSchurComplement - Gets access to a Schur complement matrix using the current Schur data within a factored matrix
9558 
9559    Logically Collective
9560 
9561    Input Parameters:
9562 +  F - the factored matrix obtained by calling `MatGetFactor()`
9563 .  *S - location where to return the Schur complement, can be `NULL`
9564 -  status - the status of the Schur complement matrix, can be `NULL`
9565 
9566    Level: advanced
9567 
9568    Notes:
9569    You must call `MatFactorSetSchurIS()` before calling this routine.
9570 
9571    Schur complement mode is currently implemented for sequential matrices with factor type of `MATSOLVERMUMPS`
9572 
9573    The routine returns a the Schur Complement stored within the data structures of the solver.
9574 
9575    If `MatFactorInvertSchurComplement()` has previously been called, the returned matrix is actually the inverse of the Schur complement.
9576 
9577    The returned matrix should not be destroyed; the caller should call `MatFactorRestoreSchurComplement()` when the object is no longer needed.
9578 
9579    Use `MatFactorCreateSchurComplement()` to create a copy of the Schur complement matrix that is within a factored matrix
9580 
9581    See `MatCreateSchurComplement()` or `MatGetSchurComplement()` for ways to create virtual or approximate Schur complements.
9582 
9583 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9584 @*/
9585 PetscErrorCode MatFactorGetSchurComplement(Mat F, Mat *S, MatFactorSchurStatus *status)
9586 {
9587   PetscFunctionBegin;
9588   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9589   if (S) PetscValidPointer(S, 2);
9590   if (status) PetscValidPointer(status, 3);
9591   if (S) *S = F->schur;
9592   if (status) *status = F->schur_status;
9593   PetscFunctionReturn(PETSC_SUCCESS);
9594 }
9595 
9596 static PetscErrorCode MatFactorUpdateSchurStatus_Private(Mat F)
9597 {
9598   Mat S = F->schur;
9599 
9600   PetscFunctionBegin;
9601   switch (F->schur_status) {
9602   case MAT_FACTOR_SCHUR_UNFACTORED: // fall-through
9603   case MAT_FACTOR_SCHUR_INVERTED:
9604     if (S) {
9605       S->ops->solve             = NULL;
9606       S->ops->matsolve          = NULL;
9607       S->ops->solvetranspose    = NULL;
9608       S->ops->matsolvetranspose = NULL;
9609       S->ops->solveadd          = NULL;
9610       S->ops->solvetransposeadd = NULL;
9611       S->factortype             = MAT_FACTOR_NONE;
9612       PetscCall(PetscFree(S->solvertype));
9613     }
9614   case MAT_FACTOR_SCHUR_FACTORED: // fall-through
9615     break;
9616   default:
9617     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9618   }
9619   PetscFunctionReturn(PETSC_SUCCESS);
9620 }
9621 
9622 /*@
9623   MatFactorRestoreSchurComplement - Restore the Schur complement matrix object obtained from a call to `MatFactorGetSchurComplement()`
9624 
9625    Logically Collective
9626 
9627    Input Parameters:
9628 +  F - the factored matrix obtained by calling `MatGetFactor()`
9629 .  *S - location where the Schur complement is stored
9630 -  status - the status of the Schur complement matrix (see `MatFactorSchurStatus`)
9631 
9632    Level: advanced
9633 
9634 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorRestoreSchurComplement()`, `MatFactorCreateSchurComplement()`, `MatFactorSchurStatus`
9635 @*/
9636 PetscErrorCode MatFactorRestoreSchurComplement(Mat F, Mat *S, MatFactorSchurStatus status)
9637 {
9638   PetscFunctionBegin;
9639   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9640   if (S) {
9641     PetscValidHeaderSpecific(*S, MAT_CLASSID, 2);
9642     *S = NULL;
9643   }
9644   F->schur_status = status;
9645   PetscCall(MatFactorUpdateSchurStatus_Private(F));
9646   PetscFunctionReturn(PETSC_SUCCESS);
9647 }
9648 
9649 /*@
9650   MatFactorSolveSchurComplementTranspose - Solve the transpose of the Schur complement system computed during the factorization step
9651 
9652    Logically Collective
9653 
9654    Input Parameters:
9655 +  F - the factored matrix obtained by calling `MatGetFactor()`
9656 .  rhs - location where the right hand side of the Schur complement system is stored
9657 -  sol - location where the solution of the Schur complement system has to be returned
9658 
9659    Level: advanced
9660 
9661    Notes:
9662    The sizes of the vectors should match the size of the Schur complement
9663 
9664    Must be called after `MatFactorSetSchurIS()`
9665 
9666 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplement()`
9667 @*/
9668 PetscErrorCode MatFactorSolveSchurComplementTranspose(Mat F, Vec rhs, Vec sol)
9669 {
9670   PetscFunctionBegin;
9671   PetscValidType(F, 1);
9672   PetscValidType(rhs, 2);
9673   PetscValidType(sol, 3);
9674   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9675   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9676   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9677   PetscCheckSameComm(F, 1, rhs, 2);
9678   PetscCheckSameComm(F, 1, sol, 3);
9679   PetscCall(MatFactorFactorizeSchurComplement(F));
9680   switch (F->schur_status) {
9681   case MAT_FACTOR_SCHUR_FACTORED:
9682     PetscCall(MatSolveTranspose(F->schur, rhs, sol));
9683     break;
9684   case MAT_FACTOR_SCHUR_INVERTED:
9685     PetscCall(MatMultTranspose(F->schur, rhs, sol));
9686     break;
9687   default:
9688     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9689   }
9690   PetscFunctionReturn(PETSC_SUCCESS);
9691 }
9692 
9693 /*@
9694   MatFactorSolveSchurComplement - Solve the Schur complement system computed during the factorization step
9695 
9696    Logically Collective
9697 
9698    Input Parameters:
9699 +  F - the factored matrix obtained by calling `MatGetFactor()`
9700 .  rhs - location where the right hand side of the Schur complement system is stored
9701 -  sol - location where the solution of the Schur complement system has to be returned
9702 
9703    Level: advanced
9704 
9705    Notes:
9706    The sizes of the vectors should match the size of the Schur complement
9707 
9708    Must be called after `MatFactorSetSchurIS()`
9709 
9710 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorSolveSchurComplementTranspose()`
9711 @*/
9712 PetscErrorCode MatFactorSolveSchurComplement(Mat F, Vec rhs, Vec sol)
9713 {
9714   PetscFunctionBegin;
9715   PetscValidType(F, 1);
9716   PetscValidType(rhs, 2);
9717   PetscValidType(sol, 3);
9718   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9719   PetscValidHeaderSpecific(rhs, VEC_CLASSID, 2);
9720   PetscValidHeaderSpecific(sol, VEC_CLASSID, 3);
9721   PetscCheckSameComm(F, 1, rhs, 2);
9722   PetscCheckSameComm(F, 1, sol, 3);
9723   PetscCall(MatFactorFactorizeSchurComplement(F));
9724   switch (F->schur_status) {
9725   case MAT_FACTOR_SCHUR_FACTORED:
9726     PetscCall(MatSolve(F->schur, rhs, sol));
9727     break;
9728   case MAT_FACTOR_SCHUR_INVERTED:
9729     PetscCall(MatMult(F->schur, rhs, sol));
9730     break;
9731   default:
9732     SETERRQ(PetscObjectComm((PetscObject)F), PETSC_ERR_SUP, "Unhandled MatFactorSchurStatus %d", F->schur_status);
9733   }
9734   PetscFunctionReturn(PETSC_SUCCESS);
9735 }
9736 
9737 PETSC_EXTERN PetscErrorCode MatSeqDenseInvertFactors_Private(Mat);
9738 #if PetscDefined(HAVE_CUDA)
9739 PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode MatSeqDenseCUDAInvertFactors_Internal(Mat);
9740 #endif
9741 
9742 /* Schur status updated in the interface */
9743 static PetscErrorCode MatFactorInvertSchurComplement_Private(Mat F)
9744 {
9745   Mat S = F->schur;
9746 
9747   PetscFunctionBegin;
9748   if (S) {
9749     PetscMPIInt size;
9750     PetscBool   isdense, isdensecuda;
9751 
9752     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)S), &size));
9753     PetscCheck(size <= 1, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not yet implemented");
9754     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSE, &isdense));
9755     PetscCall(PetscObjectTypeCompare((PetscObject)S, MATSEQDENSECUDA, &isdensecuda));
9756     PetscCheck(isdense || isdensecuda, PetscObjectComm((PetscObject)S), PETSC_ERR_SUP, "Not implemented for type %s", ((PetscObject)S)->type_name);
9757     PetscCall(PetscLogEventBegin(MAT_FactorInvS, F, 0, 0, 0));
9758     if (isdense) {
9759       PetscCall(MatSeqDenseInvertFactors_Private(S));
9760     } else if (isdensecuda) {
9761 #if defined(PETSC_HAVE_CUDA)
9762       PetscCall(MatSeqDenseCUDAInvertFactors_Internal(S));
9763 #endif
9764     }
9765     // HIP??????????????
9766     PetscCall(PetscLogEventEnd(MAT_FactorInvS, F, 0, 0, 0));
9767   }
9768   PetscFunctionReturn(PETSC_SUCCESS);
9769 }
9770 
9771 /*@
9772   MatFactorInvertSchurComplement - Invert the Schur complement matrix computed during the factorization step
9773 
9774    Logically Collective
9775 
9776    Input Parameter:
9777 .  F - the factored matrix obtained by calling `MatGetFactor()`
9778 
9779    Level: advanced
9780 
9781    Notes:
9782     Must be called after `MatFactorSetSchurIS()`.
9783 
9784    Call `MatFactorGetSchurComplement()` or  `MatFactorCreateSchurComplement()` AFTER this call to actually compute the inverse and get access to it.
9785 
9786 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorGetSchurComplement()`, `MatFactorCreateSchurComplement()`
9787 @*/
9788 PetscErrorCode MatFactorInvertSchurComplement(Mat F)
9789 {
9790   PetscFunctionBegin;
9791   PetscValidType(F, 1);
9792   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9793   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED) PetscFunctionReturn(PETSC_SUCCESS);
9794   PetscCall(MatFactorFactorizeSchurComplement(F));
9795   PetscCall(MatFactorInvertSchurComplement_Private(F));
9796   F->schur_status = MAT_FACTOR_SCHUR_INVERTED;
9797   PetscFunctionReturn(PETSC_SUCCESS);
9798 }
9799 
9800 /*@
9801   MatFactorFactorizeSchurComplement - Factorize the Schur complement matrix computed during the factorization step
9802 
9803    Logically Collective
9804 
9805    Input Parameter:
9806 .  F - the factored matrix obtained by calling `MatGetFactor()`
9807 
9808    Level: advanced
9809 
9810    Note:
9811     Must be called after `MatFactorSetSchurIS()`
9812 
9813 .seealso: [](chapter_matrices), `Mat`, `MatGetFactor()`, `MatFactorSetSchurIS()`, `MatFactorInvertSchurComplement()`
9814 @*/
9815 PetscErrorCode MatFactorFactorizeSchurComplement(Mat F)
9816 {
9817   MatFactorInfo info;
9818 
9819   PetscFunctionBegin;
9820   PetscValidType(F, 1);
9821   PetscValidHeaderSpecific(F, MAT_CLASSID, 1);
9822   if (F->schur_status == MAT_FACTOR_SCHUR_INVERTED || F->schur_status == MAT_FACTOR_SCHUR_FACTORED) PetscFunctionReturn(PETSC_SUCCESS);
9823   PetscCall(PetscLogEventBegin(MAT_FactorFactS, F, 0, 0, 0));
9824   PetscCall(PetscMemzero(&info, sizeof(MatFactorInfo)));
9825   if (F->factortype == MAT_FACTOR_CHOLESKY) { /* LDL^t regarded as Cholesky */
9826     PetscCall(MatCholeskyFactor(F->schur, NULL, &info));
9827   } else {
9828     PetscCall(MatLUFactor(F->schur, NULL, NULL, &info));
9829   }
9830   PetscCall(PetscLogEventEnd(MAT_FactorFactS, F, 0, 0, 0));
9831   F->schur_status = MAT_FACTOR_SCHUR_FACTORED;
9832   PetscFunctionReturn(PETSC_SUCCESS);
9833 }
9834 
9835 /*@
9836    MatPtAP - Creates the matrix product C = P^T * A * P
9837 
9838    Neighbor-wise Collective
9839 
9840    Input Parameters:
9841 +  A - the matrix
9842 .  P - the projection matrix
9843 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9844 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(P)), use `PETSC_DEFAULT` if you do not have a good estimate
9845           if the result is a dense matrix this is irrelevant
9846 
9847    Output Parameter:
9848 .  C - the product matrix
9849 
9850    Level: intermediate
9851 
9852    Notes:
9853    C will be created and must be destroyed by the user with `MatDestroy()`.
9854 
9855    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9856 
9857    Developer Note:
9858    For matrix types without special implementation the function fallbacks to `MatMatMult()` followed by `MatTransposeMatMult()`.
9859 
9860 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatRARt()`
9861 @*/
9862 PetscErrorCode MatPtAP(Mat A, Mat P, MatReuse scall, PetscReal fill, Mat *C)
9863 {
9864   PetscFunctionBegin;
9865   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9866   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9867 
9868   if (scall == MAT_INITIAL_MATRIX) {
9869     PetscCall(MatProductCreate(A, P, NULL, C));
9870     PetscCall(MatProductSetType(*C, MATPRODUCT_PtAP));
9871     PetscCall(MatProductSetAlgorithm(*C, "default"));
9872     PetscCall(MatProductSetFill(*C, fill));
9873 
9874     (*C)->product->api_user = PETSC_TRUE;
9875     PetscCall(MatProductSetFromOptions(*C));
9876     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);
9877     PetscCall(MatProductSymbolic(*C));
9878   } else { /* scall == MAT_REUSE_MATRIX */
9879     PetscCall(MatProductReplaceMats(A, P, NULL, *C));
9880   }
9881 
9882   PetscCall(MatProductNumeric(*C));
9883   (*C)->symmetric = A->symmetric;
9884   (*C)->spd       = A->spd;
9885   PetscFunctionReturn(PETSC_SUCCESS);
9886 }
9887 
9888 /*@
9889    MatRARt - Creates the matrix product C = R * A * R^T
9890 
9891    Neighbor-wise Collective
9892 
9893    Input Parameters:
9894 +  A - the matrix
9895 .  R - the projection matrix
9896 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9897 -  fill - expected fill as ratio of nnz(C)/nnz(A), use `PETSC_DEFAULT` if you do not have a good estimate
9898           if the result is a dense matrix this is irrelevant
9899 
9900    Output Parameter:
9901 .  C - the product matrix
9902 
9903    Level: intermediate
9904 
9905    Notes:
9906    C will be created and must be destroyed by the user with `MatDestroy()`.
9907 
9908    An alternative approach to this function is to use `MatProductCreate()` and set the desired options before the computation is done
9909 
9910    This routine is currently only implemented for pairs of `MATAIJ` matrices and classes
9911    which inherit from `MATAIJ`. Due to PETSc sparse matrix block row distribution among processes,
9912    parallel MatRARt is implemented via explicit transpose of R, which could be very expensive.
9913    We recommend using MatPtAP().
9914 
9915 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MatMatMult()`, `MatPtAP()`
9916 @*/
9917 PetscErrorCode MatRARt(Mat A, Mat R, MatReuse scall, PetscReal fill, Mat *C)
9918 {
9919   PetscFunctionBegin;
9920   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*C, 5);
9921   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9922 
9923   if (scall == MAT_INITIAL_MATRIX) {
9924     PetscCall(MatProductCreate(A, R, NULL, C));
9925     PetscCall(MatProductSetType(*C, MATPRODUCT_RARt));
9926     PetscCall(MatProductSetAlgorithm(*C, "default"));
9927     PetscCall(MatProductSetFill(*C, fill));
9928 
9929     (*C)->product->api_user = PETSC_TRUE;
9930     PetscCall(MatProductSetFromOptions(*C));
9931     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);
9932     PetscCall(MatProductSymbolic(*C));
9933   } else { /* scall == MAT_REUSE_MATRIX */
9934     PetscCall(MatProductReplaceMats(A, R, NULL, *C));
9935   }
9936 
9937   PetscCall(MatProductNumeric(*C));
9938   if (A->symmetric == PETSC_BOOL3_TRUE) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
9939   PetscFunctionReturn(PETSC_SUCCESS);
9940 }
9941 
9942 static PetscErrorCode MatProduct_Private(Mat A, Mat B, MatReuse scall, PetscReal fill, MatProductType ptype, Mat *C)
9943 {
9944   PetscFunctionBegin;
9945   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
9946 
9947   if (scall == MAT_INITIAL_MATRIX) {
9948     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_INITIAL_MATRIX and product type %s\n", MatProductTypes[ptype]));
9949     PetscCall(MatProductCreate(A, B, NULL, C));
9950     PetscCall(MatProductSetType(*C, ptype));
9951     PetscCall(MatProductSetAlgorithm(*C, MATPRODUCTALGORITHMDEFAULT));
9952     PetscCall(MatProductSetFill(*C, fill));
9953 
9954     (*C)->product->api_user = PETSC_TRUE;
9955     PetscCall(MatProductSetFromOptions(*C));
9956     PetscCall(MatProductSymbolic(*C));
9957   } else { /* scall == MAT_REUSE_MATRIX */
9958     Mat_Product *product = (*C)->product;
9959     PetscBool    isdense;
9960 
9961     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)(*C), &isdense, MATSEQDENSE, MATMPIDENSE, ""));
9962     if (isdense && product && product->type != ptype) {
9963       PetscCall(MatProductClear(*C));
9964       product = NULL;
9965     }
9966     PetscCall(PetscInfo(A, "Calling MatProduct API with MAT_REUSE_MATRIX %s product present and product type %s\n", product ? "with" : "without", MatProductTypes[ptype]));
9967     if (!product) { /* user provide the dense matrix *C without calling MatProductCreate() or reusing it from previous calls */
9968       PetscCheck(isdense, PetscObjectComm((PetscObject)(*C)), PETSC_ERR_SUP, "Call MatProductCreate() first");
9969       PetscCall(MatProductCreate_Private(A, B, NULL, *C));
9970       product           = (*C)->product;
9971       product->fill     = fill;
9972       product->api_user = PETSC_TRUE;
9973       product->clear    = PETSC_TRUE;
9974 
9975       PetscCall(MatProductSetType(*C, ptype));
9976       PetscCall(MatProductSetFromOptions(*C));
9977       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);
9978       PetscCall(MatProductSymbolic(*C));
9979     } else { /* user may change input matrices A or B when REUSE */
9980       PetscCall(MatProductReplaceMats(A, B, NULL, *C));
9981     }
9982   }
9983   PetscCall(MatProductNumeric(*C));
9984   PetscFunctionReturn(PETSC_SUCCESS);
9985 }
9986 
9987 /*@
9988    MatMatMult - Performs matrix-matrix multiplication C=A*B.
9989 
9990    Neighbor-wise Collective
9991 
9992    Input Parameters:
9993 +  A - the left matrix
9994 .  B - the right matrix
9995 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
9996 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if you do not have a good estimate
9997           if the result is a dense matrix this is irrelevant
9998 
9999    Output Parameter:
10000 .  C - the product matrix
10001 
10002    Notes:
10003    Unless scall is `MAT_REUSE_MATRIX` C will be created.
10004 
10005    `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
10006    call to this function with `MAT_INITIAL_MATRIX`.
10007 
10008    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value actually needed.
10009 
10010    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`,
10011    rather than first having `MatMatMult()` create it for you. You can NEVER do this if the matrix C is sparse.
10012 
10013    Example of Usage:
10014 .vb
10015      MatProductCreate(A,B,NULL,&C);
10016      MatProductSetType(C,MATPRODUCT_AB);
10017      MatProductSymbolic(C);
10018      MatProductNumeric(C); // compute C=A * B
10019      MatProductReplaceMats(A1,B1,NULL,C); // compute C=A1 * B1
10020      MatProductNumeric(C);
10021      MatProductReplaceMats(A2,NULL,NULL,C); // compute C=A2 * B1
10022      MatProductNumeric(C);
10023 .ve
10024 
10025    Level: intermediate
10026 
10027 .seealso: [](chapter_matrices), `Mat`, `MatProductType`, `MATPRODUCT_AB`, `MatTransposeMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`, `MatProductCreate()`, `MatProductSymbolic()`, `MatProductReplaceMats()`, `MatProductNumeric()`
10028 @*/
10029 PetscErrorCode MatMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10030 {
10031   PetscFunctionBegin;
10032   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AB, C));
10033   PetscFunctionReturn(PETSC_SUCCESS);
10034 }
10035 
10036 /*@
10037    MatMatTransposeMult - Performs matrix-matrix multiplication C=A*B^T.
10038 
10039    Neighbor-wise Collective
10040 
10041    Input Parameters:
10042 +  A - the left matrix
10043 .  B - the right matrix
10044 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10045 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10046 
10047    Output Parameter:
10048 .  C - the product matrix
10049 
10050    Level: intermediate
10051 
10052    Notes:
10053    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10054 
10055    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call
10056 
10057    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10058    actually needed.
10059 
10060    This routine is currently only implemented for pairs of `MATSEQAIJ` matrices, for the `MATSEQDENSE` class,
10061    and for pairs of `MATMPIDENSE` matrices.
10062 
10063    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABt`
10064 
10065    Options Database Keys:
10066 .  -matmattransmult_mpidense_mpidense_via {allgatherv,cyclic} - Choose between algorithms for `MATMPIDENSE` matrices: the
10067               first redundantly copies the transposed B matrix on each process and requiers O(log P) communication complexity;
10068               the second never stores more than one portion of the B matrix at a time by requires O(P) communication complexity.
10069 
10070 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABt`, `MatMatMult()`, `MatTransposeMatMult()` `MatPtAP()`, `MatProductCreate()`, `MatProductAlgorithm`, `MatProductType`, `MATPRODUCT_ABt`
10071 @*/
10072 PetscErrorCode MatMatTransposeMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10073 {
10074   PetscFunctionBegin;
10075   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_ABt, C));
10076   if (A == B) PetscCall(MatSetOption(*C, MAT_SYMMETRIC, PETSC_TRUE));
10077   PetscFunctionReturn(PETSC_SUCCESS);
10078 }
10079 
10080 /*@
10081    MatTransposeMatMult - Performs matrix-matrix multiplication C=A^T*B.
10082 
10083    Neighbor-wise Collective
10084 
10085    Input Parameters:
10086 +  A - the left matrix
10087 .  B - the right matrix
10088 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10089 -  fill - expected fill as ratio of nnz(C)/(nnz(A) + nnz(B)), use `PETSC_DEFAULT` if not known
10090 
10091    Output Parameter:
10092 .  C - the product matrix
10093 
10094    Level: intermediate
10095 
10096    Notes:
10097    C will be created if `MAT_INITIAL_MATRIX` and must be destroyed by the user with `MatDestroy()`.
10098 
10099    `MAT_REUSE_MATRIX` can only be used if the matrices A and B have the same nonzero pattern as in the previous call.
10100 
10101    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_AtB`
10102 
10103    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10104    actually needed.
10105 
10106    This routine is currently implemented for pairs of `MATAIJ` matrices and pairs of `MATSEQDENSE` matrices and classes
10107    which inherit from `MATSEQAIJ`.  C will be of the same type as the input matrices.
10108 
10109 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_AtB`, `MatMatMult()`, `MatMatTransposeMult()`, `MatPtAP()`
10110 @*/
10111 PetscErrorCode MatTransposeMatMult(Mat A, Mat B, MatReuse scall, PetscReal fill, Mat *C)
10112 {
10113   PetscFunctionBegin;
10114   PetscCall(MatProduct_Private(A, B, scall, fill, MATPRODUCT_AtB, C));
10115   PetscFunctionReturn(PETSC_SUCCESS);
10116 }
10117 
10118 /*@
10119    MatMatMatMult - Performs matrix-matrix-matrix multiplication D=A*B*C.
10120 
10121    Neighbor-wise Collective
10122 
10123    Input Parameters:
10124 +  A - the left matrix
10125 .  B - the middle matrix
10126 .  C - the right matrix
10127 .  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10128 -  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
10129           if the result is a dense matrix this is irrelevant
10130 
10131    Output Parameter:
10132 .  D - the product matrix
10133 
10134    Level: intermediate
10135 
10136    Notes:
10137    Unless scall is `MAT_REUSE_MATRIX` D will be created.
10138 
10139    `MAT_REUSE_MATRIX` can only be used if the matrices A, B and C have the same nonzero pattern as in the previous call
10140 
10141    This routine is shorthand for using `MatProductCreate()` with the `MatProductType` of `MATPRODUCT_ABC`
10142 
10143    To determine the correct fill value, run with -info and search for the string "Fill ratio" to see the value
10144    actually needed.
10145 
10146    If you have many matrices with the same non-zero structure to multiply, you
10147    should use `MAT_REUSE_MATRIX` in all calls but the first
10148 
10149 .seealso: [](chapter_matrices), `Mat`, `MatProductCreate()`, `MATPRODUCT_ABC`, `MatMatMult`, `MatPtAP()`, `MatMatTransposeMult()`, `MatTransposeMatMult()`
10150 @*/
10151 PetscErrorCode MatMatMatMult(Mat A, Mat B, Mat C, MatReuse scall, PetscReal fill, Mat *D)
10152 {
10153   PetscFunctionBegin;
10154   if (scall == MAT_REUSE_MATRIX) MatCheckProduct(*D, 6);
10155   PetscCheck(scall != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10156 
10157   if (scall == MAT_INITIAL_MATRIX) {
10158     PetscCall(MatProductCreate(A, B, C, D));
10159     PetscCall(MatProductSetType(*D, MATPRODUCT_ABC));
10160     PetscCall(MatProductSetAlgorithm(*D, "default"));
10161     PetscCall(MatProductSetFill(*D, fill));
10162 
10163     (*D)->product->api_user = PETSC_TRUE;
10164     PetscCall(MatProductSetFromOptions(*D));
10165     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,
10166                ((PetscObject)C)->type_name);
10167     PetscCall(MatProductSymbolic(*D));
10168   } else { /* user may change input matrices when REUSE */
10169     PetscCall(MatProductReplaceMats(A, B, C, *D));
10170   }
10171   PetscCall(MatProductNumeric(*D));
10172   PetscFunctionReturn(PETSC_SUCCESS);
10173 }
10174 
10175 /*@
10176    MatCreateRedundantMatrix - Create redundant matrices and put them into processors of subcommunicators.
10177 
10178    Collective
10179 
10180    Input Parameters:
10181 +  mat - the matrix
10182 .  nsubcomm - the number of subcommunicators (= number of redundant parallel or sequential matrices)
10183 .  subcomm - MPI communicator split from the communicator where mat resides in (or `MPI_COMM_NULL` if nsubcomm is used)
10184 -  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10185 
10186    Output Parameter:
10187 .  matredundant - redundant matrix
10188 
10189    Level: advanced
10190 
10191    Notes:
10192    `MAT_REUSE_MATRIX` can only be used when the nonzero structure of the
10193    original matrix has not changed from that last call to MatCreateRedundantMatrix().
10194 
10195    This routine creates the duplicated matrices in the subcommunicators; you should NOT create them before
10196    calling it.
10197 
10198    `PetscSubcommCreate()` can be used to manage the creation of the subcomm but need not be.
10199 
10200 .seealso: [](chapter_matrices), `Mat`, `MatDestroy()`, `PetscSubcommCreate()`, `PetscSubComm`
10201 @*/
10202 PetscErrorCode MatCreateRedundantMatrix(Mat mat, PetscInt nsubcomm, MPI_Comm subcomm, MatReuse reuse, Mat *matredundant)
10203 {
10204   MPI_Comm       comm;
10205   PetscMPIInt    size;
10206   PetscInt       mloc_sub, nloc_sub, rstart, rend, M = mat->rmap->N, N = mat->cmap->N, bs = mat->rmap->bs;
10207   Mat_Redundant *redund     = NULL;
10208   PetscSubcomm   psubcomm   = NULL;
10209   MPI_Comm       subcomm_in = subcomm;
10210   Mat           *matseq;
10211   IS             isrow, iscol;
10212   PetscBool      newsubcomm = PETSC_FALSE;
10213 
10214   PetscFunctionBegin;
10215   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10216   if (nsubcomm && reuse == MAT_REUSE_MATRIX) {
10217     PetscValidPointer(*matredundant, 5);
10218     PetscValidHeaderSpecific(*matredundant, MAT_CLASSID, 5);
10219   }
10220 
10221   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
10222   if (size == 1 || nsubcomm == 1) {
10223     if (reuse == MAT_INITIAL_MATRIX) {
10224       PetscCall(MatDuplicate(mat, MAT_COPY_VALUES, matredundant));
10225     } else {
10226       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");
10227       PetscCall(MatCopy(mat, *matredundant, SAME_NONZERO_PATTERN));
10228     }
10229     PetscFunctionReturn(PETSC_SUCCESS);
10230   }
10231 
10232   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10233   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10234   MatCheckPreallocated(mat, 1);
10235 
10236   PetscCall(PetscLogEventBegin(MAT_RedundantMat, mat, 0, 0, 0));
10237   if (subcomm_in == MPI_COMM_NULL && reuse == MAT_INITIAL_MATRIX) { /* get subcomm if user does not provide subcomm */
10238     /* create psubcomm, then get subcomm */
10239     PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10240     PetscCallMPI(MPI_Comm_size(comm, &size));
10241     PetscCheck(nsubcomm >= 1 && nsubcomm <= size, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "nsubcomm must between 1 and %d", size);
10242 
10243     PetscCall(PetscSubcommCreate(comm, &psubcomm));
10244     PetscCall(PetscSubcommSetNumber(psubcomm, nsubcomm));
10245     PetscCall(PetscSubcommSetType(psubcomm, PETSC_SUBCOMM_CONTIGUOUS));
10246     PetscCall(PetscSubcommSetFromOptions(psubcomm));
10247     PetscCall(PetscCommDuplicate(PetscSubcommChild(psubcomm), &subcomm, NULL));
10248     newsubcomm = PETSC_TRUE;
10249     PetscCall(PetscSubcommDestroy(&psubcomm));
10250   }
10251 
10252   /* get isrow, iscol and a local sequential matrix matseq[0] */
10253   if (reuse == MAT_INITIAL_MATRIX) {
10254     mloc_sub = PETSC_DECIDE;
10255     nloc_sub = PETSC_DECIDE;
10256     if (bs < 1) {
10257       PetscCall(PetscSplitOwnership(subcomm, &mloc_sub, &M));
10258       PetscCall(PetscSplitOwnership(subcomm, &nloc_sub, &N));
10259     } else {
10260       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &mloc_sub, &M));
10261       PetscCall(PetscSplitOwnershipBlock(subcomm, bs, &nloc_sub, &N));
10262     }
10263     PetscCallMPI(MPI_Scan(&mloc_sub, &rend, 1, MPIU_INT, MPI_SUM, subcomm));
10264     rstart = rend - mloc_sub;
10265     PetscCall(ISCreateStride(PETSC_COMM_SELF, mloc_sub, rstart, 1, &isrow));
10266     PetscCall(ISCreateStride(PETSC_COMM_SELF, N, 0, 1, &iscol));
10267   } else { /* reuse == MAT_REUSE_MATRIX */
10268     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");
10269     /* retrieve subcomm */
10270     PetscCall(PetscObjectGetComm((PetscObject)(*matredundant), &subcomm));
10271     redund = (*matredundant)->redundant;
10272     isrow  = redund->isrow;
10273     iscol  = redund->iscol;
10274     matseq = redund->matseq;
10275   }
10276   PetscCall(MatCreateSubMatrices(mat, 1, &isrow, &iscol, reuse, &matseq));
10277 
10278   /* get matredundant over subcomm */
10279   if (reuse == MAT_INITIAL_MATRIX) {
10280     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], nloc_sub, reuse, matredundant));
10281 
10282     /* create a supporting struct and attach it to C for reuse */
10283     PetscCall(PetscNew(&redund));
10284     (*matredundant)->redundant = redund;
10285     redund->isrow              = isrow;
10286     redund->iscol              = iscol;
10287     redund->matseq             = matseq;
10288     if (newsubcomm) {
10289       redund->subcomm = subcomm;
10290     } else {
10291       redund->subcomm = MPI_COMM_NULL;
10292     }
10293   } else {
10294     PetscCall(MatCreateMPIMatConcatenateSeqMat(subcomm, matseq[0], PETSC_DECIDE, reuse, matredundant));
10295   }
10296 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_HIP)
10297   if (matseq[0]->boundtocpu && matseq[0]->bindingpropagates) {
10298     PetscCall(MatBindToCPU(*matredundant, PETSC_TRUE));
10299     PetscCall(MatSetBindingPropagates(*matredundant, PETSC_TRUE));
10300   }
10301 #endif
10302   PetscCall(PetscLogEventEnd(MAT_RedundantMat, mat, 0, 0, 0));
10303   PetscFunctionReturn(PETSC_SUCCESS);
10304 }
10305 
10306 /*@C
10307    MatGetMultiProcBlock - Create multiple 'parallel submatrices' from
10308    a given `Mat`. Each submatrix can span multiple procs.
10309 
10310    Collective
10311 
10312    Input Parameters:
10313 +  mat - the matrix
10314 .  subcomm - the sub communicator obtained as if by `MPI_Comm_split(PetscObjectComm((PetscObject)mat))`
10315 -  scall - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10316 
10317    Output Parameter:
10318 .  subMat - parallel sub-matrices each spanning a given `subcomm`
10319 
10320   Level: advanced
10321 
10322   Notes:
10323   The submatrix partition across processors is dictated by `subComm` a
10324   communicator obtained by `MPI_comm_split()` or via `PetscSubcommCreate()`. The `subComm`
10325   is not restricted to be grouped with consecutive original ranks.
10326 
10327   Due the `MPI_Comm_split()` usage, the parallel layout of the submatrices
10328   map directly to the layout of the original matrix [wrt the local
10329   row,col partitioning]. So the original 'DiagonalMat' naturally maps
10330   into the 'DiagonalMat' of the `subMat`, hence it is used directly from
10331   the `subMat`. However the offDiagMat looses some columns - and this is
10332   reconstructed with `MatSetValues()`
10333 
10334   This is used by `PCBJACOBI` when a single block spans multiple MPI ranks
10335 
10336 .seealso: [](chapter_matrices), `Mat`, `MatCreateRedundantMatrix()`, `MatCreateSubMatrices()`, `PCBJACOBI`
10337 @*/
10338 PetscErrorCode MatGetMultiProcBlock(Mat mat, MPI_Comm subComm, MatReuse scall, Mat *subMat)
10339 {
10340   PetscMPIInt commsize, subCommSize;
10341 
10342   PetscFunctionBegin;
10343   PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &commsize));
10344   PetscCallMPI(MPI_Comm_size(subComm, &subCommSize));
10345   PetscCheck(subCommSize <= commsize, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_OUTOFRANGE, "CommSize %d < SubCommZize %d", commsize, subCommSize);
10346 
10347   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");
10348   PetscCall(PetscLogEventBegin(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10349   PetscUseTypeMethod(mat, getmultiprocblock, subComm, scall, subMat);
10350   PetscCall(PetscLogEventEnd(MAT_GetMultiProcBlock, mat, 0, 0, 0));
10351   PetscFunctionReturn(PETSC_SUCCESS);
10352 }
10353 
10354 /*@
10355    MatGetLocalSubMatrix - Gets a reference to a submatrix specified in local numbering
10356 
10357    Not Collective
10358 
10359    Input Parameters:
10360 +  mat - matrix to extract local submatrix from
10361 .  isrow - local row indices for submatrix
10362 -  iscol - local column indices for submatrix
10363 
10364    Output Parameter:
10365 .  submat - the submatrix
10366 
10367    Level: intermediate
10368 
10369    Notes:
10370    `submat` should be disposed of with `MatRestoreLocalSubMatrix()`.
10371 
10372    Depending on the format of `mat`, the returned submat may not implement `MatMult()`.  Its communicator may be
10373    the same as mat, it may be `PETSC_COMM_SELF`, or some other subcomm of `mat`'s.
10374 
10375    `submat` always implements `MatSetValuesLocal()`.  If `isrow` and `iscol` have the same block size, then
10376    `MatSetValuesBlockedLocal()` will also be implemented.
10377 
10378    `mat` must have had a `ISLocalToGlobalMapping` provided to it with `MatSetLocalToGlobalMapping()`.
10379    Matrices obtained with `DMCreateMatrix()` generally already have the local to global mapping provided.
10380 
10381 .seealso: [](chapter_matrices), `Mat`, `MatRestoreLocalSubMatrix()`, `MatCreateLocalRef()`, `MatSetLocalToGlobalMapping()`
10382 @*/
10383 PetscErrorCode MatGetLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10384 {
10385   PetscFunctionBegin;
10386   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10387   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10388   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10389   PetscCheckSameComm(isrow, 2, iscol, 3);
10390   PetscValidPointer(submat, 4);
10391   PetscCheck(mat->rmap->mapping, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Matrix must have local to global mapping provided before this call");
10392 
10393   if (mat->ops->getlocalsubmatrix) {
10394     PetscUseTypeMethod(mat, getlocalsubmatrix, isrow, iscol, submat);
10395   } else {
10396     PetscCall(MatCreateLocalRef(mat, isrow, iscol, submat));
10397   }
10398   PetscFunctionReturn(PETSC_SUCCESS);
10399 }
10400 
10401 /*@
10402    MatRestoreLocalSubMatrix - Restores a reference to a submatrix specified in local numbering obtained with `MatGetLocalSubMatrix()`
10403 
10404    Not Collective
10405 
10406    Input Parameters:
10407 +  mat - matrix to extract local submatrix from
10408 .  isrow - local row indices for submatrix
10409 .  iscol - local column indices for submatrix
10410 -  submat - the submatrix
10411 
10412    Level: intermediate
10413 
10414 .seealso: [](chapter_matrices), `Mat`, `MatGetLocalSubMatrix()`
10415 @*/
10416 PetscErrorCode MatRestoreLocalSubMatrix(Mat mat, IS isrow, IS iscol, Mat *submat)
10417 {
10418   PetscFunctionBegin;
10419   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10420   PetscValidHeaderSpecific(isrow, IS_CLASSID, 2);
10421   PetscValidHeaderSpecific(iscol, IS_CLASSID, 3);
10422   PetscCheckSameComm(isrow, 2, iscol, 3);
10423   PetscValidPointer(submat, 4);
10424   if (*submat) PetscValidHeaderSpecific(*submat, MAT_CLASSID, 4);
10425 
10426   if (mat->ops->restorelocalsubmatrix) {
10427     PetscUseTypeMethod(mat, restorelocalsubmatrix, isrow, iscol, submat);
10428   } else {
10429     PetscCall(MatDestroy(submat));
10430   }
10431   *submat = NULL;
10432   PetscFunctionReturn(PETSC_SUCCESS);
10433 }
10434 
10435 /*@
10436    MatFindZeroDiagonals - Finds all the rows of a matrix that have zero or no diagonal entry in the matrix
10437 
10438    Collective
10439 
10440    Input Parameter:
10441 .  mat - the matrix
10442 
10443    Output Parameter:
10444 .  is - if any rows have zero diagonals this contains the list of them
10445 
10446    Level: developer
10447 
10448 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10449 @*/
10450 PetscErrorCode MatFindZeroDiagonals(Mat mat, IS *is)
10451 {
10452   PetscFunctionBegin;
10453   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10454   PetscValidType(mat, 1);
10455   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10456   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10457 
10458   if (!mat->ops->findzerodiagonals) {
10459     Vec                diag;
10460     const PetscScalar *a;
10461     PetscInt          *rows;
10462     PetscInt           rStart, rEnd, r, nrow = 0;
10463 
10464     PetscCall(MatCreateVecs(mat, &diag, NULL));
10465     PetscCall(MatGetDiagonal(mat, diag));
10466     PetscCall(MatGetOwnershipRange(mat, &rStart, &rEnd));
10467     PetscCall(VecGetArrayRead(diag, &a));
10468     for (r = 0; r < rEnd - rStart; ++r)
10469       if (a[r] == 0.0) ++nrow;
10470     PetscCall(PetscMalloc1(nrow, &rows));
10471     nrow = 0;
10472     for (r = 0; r < rEnd - rStart; ++r)
10473       if (a[r] == 0.0) rows[nrow++] = r + rStart;
10474     PetscCall(VecRestoreArrayRead(diag, &a));
10475     PetscCall(VecDestroy(&diag));
10476     PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)mat), nrow, rows, PETSC_OWN_POINTER, is));
10477   } else {
10478     PetscUseTypeMethod(mat, findzerodiagonals, is);
10479   }
10480   PetscFunctionReturn(PETSC_SUCCESS);
10481 }
10482 
10483 /*@
10484    MatFindOffBlockDiagonalEntries - Finds all the rows of a matrix that have entries outside of the main diagonal block (defined by the matrix block size)
10485 
10486    Collective
10487 
10488    Input Parameter:
10489 .  mat - the matrix
10490 
10491    Output Parameter:
10492 .  is - contains the list of rows with off block diagonal entries
10493 
10494    Level: developer
10495 
10496 .seealso: [](chapter_matrices), `Mat`, `MatMultTranspose()`, `MatMultAdd()`, `MatMultTransposeAdd()`
10497 @*/
10498 PetscErrorCode MatFindOffBlockDiagonalEntries(Mat mat, IS *is)
10499 {
10500   PetscFunctionBegin;
10501   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10502   PetscValidType(mat, 1);
10503   PetscCheck(mat->assembled, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10504   PetscCheck(!mat->factortype, PetscObjectComm((PetscObject)mat), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10505 
10506   PetscUseTypeMethod(mat, findoffblockdiagonalentries, is);
10507   PetscFunctionReturn(PETSC_SUCCESS);
10508 }
10509 
10510 /*@C
10511   MatInvertBlockDiagonal - Inverts the block diagonal entries.
10512 
10513   Collective; No Fortran Support
10514 
10515   Input Parameter:
10516 . mat - the matrix
10517 
10518   Output Parameter:
10519 . values - the block inverses in column major order (FORTRAN-like)
10520 
10521   Level: advanced
10522 
10523    Notes:
10524    The size of the blocks is determined by the block size of the matrix.
10525 
10526    The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10527 
10528    The blocks all have the same size, use `MatInvertVariableBlockDiagonal()` for variable block size
10529 
10530 .seealso: [](chapter_matrices), `Mat`, `MatInvertVariableBlockEnvelope()`, `MatInvertBlockDiagonalMat()`
10531 @*/
10532 PetscErrorCode MatInvertBlockDiagonal(Mat mat, const PetscScalar **values)
10533 {
10534   PetscFunctionBegin;
10535   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10536   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10537   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10538   PetscUseTypeMethod(mat, invertblockdiagonal, values);
10539   PetscFunctionReturn(PETSC_SUCCESS);
10540 }
10541 
10542 /*@C
10543   MatInvertVariableBlockDiagonal - Inverts the point block diagonal entries.
10544 
10545   Collective; No Fortran Support
10546 
10547   Input Parameters:
10548 + mat - the matrix
10549 . nblocks - the number of blocks on the process, set with `MatSetVariableBlockSizes()`
10550 - bsizes - the size of each block on the process, set with `MatSetVariableBlockSizes()`
10551 
10552   Output Parameter:
10553 . values - the block inverses in column major order (FORTRAN-like)
10554 
10555   Level: advanced
10556 
10557   Notes:
10558   Use `MatInvertBlockDiagonal()` if all blocks have the same size
10559 
10560   The blocks never overlap between two MPI ranks, use `MatInvertVariableBlockEnvelope()` for that case
10561 
10562 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`, `MatSetVariableBlockSizes()`, `MatInvertVariableBlockEnvelope()`
10563 @*/
10564 PetscErrorCode MatInvertVariableBlockDiagonal(Mat mat, PetscInt nblocks, const PetscInt *bsizes, PetscScalar *values)
10565 {
10566   PetscFunctionBegin;
10567   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10568   PetscCheck(mat->assembled, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix");
10569   PetscCheck(!mat->factortype, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix");
10570   PetscUseTypeMethod(mat, invertvariableblockdiagonal, nblocks, bsizes, values);
10571   PetscFunctionReturn(PETSC_SUCCESS);
10572 }
10573 
10574 /*@
10575   MatInvertBlockDiagonalMat - set the values of matrix C to be the inverted block diagonal of matrix A
10576 
10577   Collective
10578 
10579   Input Parameters:
10580 + A - the matrix
10581 - C - matrix with inverted block diagonal of `A`.  This matrix should be created and may have its type set.
10582 
10583   Level: advanced
10584 
10585   Note:
10586   The blocksize of the matrix is used to determine the blocks on the diagonal of `C`
10587 
10588 .seealso: [](chapter_matrices), `Mat`, `MatInvertBlockDiagonal()`
10589 @*/
10590 PetscErrorCode MatInvertBlockDiagonalMat(Mat A, Mat C)
10591 {
10592   const PetscScalar *vals;
10593   PetscInt          *dnnz;
10594   PetscInt           m, rstart, rend, bs, i, j;
10595 
10596   PetscFunctionBegin;
10597   PetscCall(MatInvertBlockDiagonal(A, &vals));
10598   PetscCall(MatGetBlockSize(A, &bs));
10599   PetscCall(MatGetLocalSize(A, &m, NULL));
10600   PetscCall(MatSetLayouts(C, A->rmap, A->cmap));
10601   PetscCall(PetscMalloc1(m / bs, &dnnz));
10602   for (j = 0; j < m / bs; j++) dnnz[j] = 1;
10603   PetscCall(MatXAIJSetPreallocation(C, bs, dnnz, NULL, NULL, NULL));
10604   PetscCall(PetscFree(dnnz));
10605   PetscCall(MatGetOwnershipRange(C, &rstart, &rend));
10606   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_FALSE));
10607   for (i = rstart / bs; i < rend / bs; i++) PetscCall(MatSetValuesBlocked(C, 1, &i, 1, &i, &vals[(i - rstart / bs) * bs * bs], INSERT_VALUES));
10608   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
10609   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
10610   PetscCall(MatSetOption(C, MAT_ROW_ORIENTED, PETSC_TRUE));
10611   PetscFunctionReturn(PETSC_SUCCESS);
10612 }
10613 
10614 /*@C
10615     MatTransposeColoringDestroy - Destroys a coloring context for matrix product C=A*B^T that was created
10616     via `MatTransposeColoringCreate()`.
10617 
10618     Collective
10619 
10620     Input Parameter:
10621 .   c - coloring context
10622 
10623     Level: intermediate
10624 
10625 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`
10626 @*/
10627 PetscErrorCode MatTransposeColoringDestroy(MatTransposeColoring *c)
10628 {
10629   MatTransposeColoring matcolor = *c;
10630 
10631   PetscFunctionBegin;
10632   if (!matcolor) PetscFunctionReturn(PETSC_SUCCESS);
10633   if (--((PetscObject)matcolor)->refct > 0) {
10634     matcolor = NULL;
10635     PetscFunctionReturn(PETSC_SUCCESS);
10636   }
10637 
10638   PetscCall(PetscFree3(matcolor->ncolumns, matcolor->nrows, matcolor->colorforrow));
10639   PetscCall(PetscFree(matcolor->rows));
10640   PetscCall(PetscFree(matcolor->den2sp));
10641   PetscCall(PetscFree(matcolor->colorforcol));
10642   PetscCall(PetscFree(matcolor->columns));
10643   if (matcolor->brows > 0) PetscCall(PetscFree(matcolor->lstart));
10644   PetscCall(PetscHeaderDestroy(c));
10645   PetscFunctionReturn(PETSC_SUCCESS);
10646 }
10647 
10648 /*@C
10649     MatTransColoringApplySpToDen - Given a symbolic matrix product C=A*B^T for which
10650     a `MatTransposeColoring` context has been created, computes a dense B^T by applying
10651     `MatTransposeColoring` to sparse B.
10652 
10653     Collective
10654 
10655     Input Parameters:
10656 +   coloring - coloring context created with `MatTransposeColoringCreate()`
10657 -   B - sparse matrix
10658 
10659     Output Parameter:
10660 .   Btdense - dense matrix B^T
10661 
10662     Level: developer
10663 
10664     Note:
10665     These are used internally for some implementations of `MatRARt()`
10666 
10667 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplyDenToSp()`
10668 @*/
10669 PetscErrorCode MatTransColoringApplySpToDen(MatTransposeColoring coloring, Mat B, Mat Btdense)
10670 {
10671   PetscFunctionBegin;
10672   PetscValidHeaderSpecific(coloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10673   PetscValidHeaderSpecific(B, MAT_CLASSID, 2);
10674   PetscValidHeaderSpecific(Btdense, MAT_CLASSID, 3);
10675 
10676   PetscCall((*B->ops->transcoloringapplysptoden)(coloring, B, Btdense));
10677   PetscFunctionReturn(PETSC_SUCCESS);
10678 }
10679 
10680 /*@C
10681     MatTransColoringApplyDenToSp - Given a symbolic matrix product Csp=A*B^T for which
10682     a `MatTransposeColoring` context has been created and a dense matrix Cden=A*Btdense
10683     in which Btdens is obtained from `MatTransColoringApplySpToDen()`, recover sparse matrix
10684     `Csp` from `Cden`.
10685 
10686     Collective
10687 
10688     Input Parameters:
10689 +   matcoloring - coloring context created with `MatTransposeColoringCreate()`
10690 -   Cden - matrix product of a sparse matrix and a dense matrix Btdense
10691 
10692     Output Parameter:
10693 .   Csp - sparse matrix
10694 
10695     Level: developer
10696 
10697     Note:
10698     These are used internally for some implementations of `MatRARt()`
10699 
10700 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringCreate()`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`
10701 @*/
10702 PetscErrorCode MatTransColoringApplyDenToSp(MatTransposeColoring matcoloring, Mat Cden, Mat Csp)
10703 {
10704   PetscFunctionBegin;
10705   PetscValidHeaderSpecific(matcoloring, MAT_TRANSPOSECOLORING_CLASSID, 1);
10706   PetscValidHeaderSpecific(Cden, MAT_CLASSID, 2);
10707   PetscValidHeaderSpecific(Csp, MAT_CLASSID, 3);
10708 
10709   PetscCall((*Csp->ops->transcoloringapplydentosp)(matcoloring, Cden, Csp));
10710   PetscCall(MatAssemblyBegin(Csp, MAT_FINAL_ASSEMBLY));
10711   PetscCall(MatAssemblyEnd(Csp, MAT_FINAL_ASSEMBLY));
10712   PetscFunctionReturn(PETSC_SUCCESS);
10713 }
10714 
10715 /*@C
10716    MatTransposeColoringCreate - Creates a matrix coloring context for the matrix product C=A*B^T.
10717 
10718    Collective
10719 
10720    Input Parameters:
10721 +  mat - the matrix product C
10722 -  iscoloring - the coloring of the matrix; usually obtained with `MatColoringCreate()` or `DMCreateColoring()`
10723 
10724     Output Parameter:
10725 .   color - the new coloring context
10726 
10727     Level: intermediate
10728 
10729 .seealso: [](chapter_matrices), `Mat`, `MatTransposeColoringDestroy()`, `MatTransColoringApplySpToDen()`,
10730           `MatTransColoringApplyDenToSp()`
10731 @*/
10732 PetscErrorCode MatTransposeColoringCreate(Mat mat, ISColoring iscoloring, MatTransposeColoring *color)
10733 {
10734   MatTransposeColoring c;
10735   MPI_Comm             comm;
10736 
10737   PetscFunctionBegin;
10738   PetscCall(PetscLogEventBegin(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10739   PetscCall(PetscObjectGetComm((PetscObject)mat, &comm));
10740   PetscCall(PetscHeaderCreate(c, MAT_TRANSPOSECOLORING_CLASSID, "MatTransposeColoring", "Matrix product C=A*B^T via coloring", "Mat", comm, MatTransposeColoringDestroy, NULL));
10741 
10742   c->ctype = iscoloring->ctype;
10743   PetscUseTypeMethod(mat, transposecoloringcreate, iscoloring, c);
10744 
10745   *color = c;
10746   PetscCall(PetscLogEventEnd(MAT_TransposeColoringCreate, mat, 0, 0, 0));
10747   PetscFunctionReturn(PETSC_SUCCESS);
10748 }
10749 
10750 /*@
10751       MatGetNonzeroState - Returns a 64-bit integer representing the current state of nonzeros in the matrix. If the
10752         matrix has had no new nonzero locations added to (or removed from) the matrix since the previous call then the value will be the
10753         same, otherwise it will be larger
10754 
10755      Not Collective
10756 
10757   Input Parameter:
10758 .    A  - the matrix
10759 
10760   Output Parameter:
10761 .    state - the current state
10762 
10763   Level: intermediate
10764 
10765   Notes:
10766     You can only compare states from two different calls to the SAME matrix, you cannot compare calls between
10767          different matrices
10768 
10769     Use `PetscObjectStateGet()` to check for changes to the numerical values in a matrix
10770 
10771     Use the result of `PetscObjectGetId()` to compare if a previously checked matrix is the same as the current matrix, do not compare object pointers.
10772 
10773 .seealso: [](chapter_matrices), `Mat`, `PetscObjectStateGet()`, `PetscObjectGetId()`
10774 @*/
10775 PetscErrorCode MatGetNonzeroState(Mat mat, PetscObjectState *state)
10776 {
10777   PetscFunctionBegin;
10778   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10779   *state = mat->nonzerostate;
10780   PetscFunctionReturn(PETSC_SUCCESS);
10781 }
10782 
10783 /*@
10784       MatCreateMPIMatConcatenateSeqMat - Creates a single large PETSc matrix by concatenating sequential
10785                  matrices from each processor
10786 
10787     Collective
10788 
10789    Input Parameters:
10790 +    comm - the communicators the parallel matrix will live on
10791 .    seqmat - the input sequential matrices
10792 .    n - number of local columns (or `PETSC_DECIDE`)
10793 -    reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10794 
10795    Output Parameter:
10796 .    mpimat - the parallel matrix generated
10797 
10798     Level: developer
10799 
10800    Note:
10801     The number of columns of the matrix in EACH processor MUST be the same.
10802 
10803 .seealso: [](chapter_matrices), `Mat`
10804 @*/
10805 PetscErrorCode MatCreateMPIMatConcatenateSeqMat(MPI_Comm comm, Mat seqmat, PetscInt n, MatReuse reuse, Mat *mpimat)
10806 {
10807   PetscMPIInt size;
10808 
10809   PetscFunctionBegin;
10810   PetscCallMPI(MPI_Comm_size(comm, &size));
10811   if (size == 1) {
10812     if (reuse == MAT_INITIAL_MATRIX) {
10813       PetscCall(MatDuplicate(seqmat, MAT_COPY_VALUES, mpimat));
10814     } else {
10815       PetscCall(MatCopy(seqmat, *mpimat, SAME_NONZERO_PATTERN));
10816     }
10817     PetscFunctionReturn(PETSC_SUCCESS);
10818   }
10819 
10820   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");
10821 
10822   PetscCall(PetscLogEventBegin(MAT_Merge, seqmat, 0, 0, 0));
10823   PetscCall((*seqmat->ops->creatempimatconcatenateseqmat)(comm, seqmat, n, reuse, mpimat));
10824   PetscCall(PetscLogEventEnd(MAT_Merge, seqmat, 0, 0, 0));
10825   PetscFunctionReturn(PETSC_SUCCESS);
10826 }
10827 
10828 /*@
10829      MatSubdomainsCreateCoalesce - Creates index subdomains by coalescing adjacent ranks' ownership ranges.
10830 
10831     Collective
10832 
10833    Input Parameters:
10834 +    A   - the matrix to create subdomains from
10835 -    N   - requested number of subdomains
10836 
10837    Output Parameters:
10838 +    n   - number of subdomains resulting on this rank
10839 -    iss - `IS` list with indices of subdomains on this rank
10840 
10841     Level: advanced
10842 
10843     Note:
10844     The number of subdomains must be smaller than the communicator size
10845 
10846 .seealso: [](chapter_matrices), `Mat`, `IS`
10847 @*/
10848 PetscErrorCode MatSubdomainsCreateCoalesce(Mat A, PetscInt N, PetscInt *n, IS *iss[])
10849 {
10850   MPI_Comm    comm, subcomm;
10851   PetscMPIInt size, rank, color;
10852   PetscInt    rstart, rend, k;
10853 
10854   PetscFunctionBegin;
10855   PetscCall(PetscObjectGetComm((PetscObject)A, &comm));
10856   PetscCallMPI(MPI_Comm_size(comm, &size));
10857   PetscCallMPI(MPI_Comm_rank(comm, &rank));
10858   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);
10859   *n    = 1;
10860   k     = ((PetscInt)size) / N + ((PetscInt)size % N > 0); /* There are up to k ranks to a color */
10861   color = rank / k;
10862   PetscCallMPI(MPI_Comm_split(comm, color, rank, &subcomm));
10863   PetscCall(PetscMalloc1(1, iss));
10864   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
10865   PetscCall(ISCreateStride(subcomm, rend - rstart, rstart, 1, iss[0]));
10866   PetscCallMPI(MPI_Comm_free(&subcomm));
10867   PetscFunctionReturn(PETSC_SUCCESS);
10868 }
10869 
10870 /*@
10871    MatGalerkin - Constructs the coarse grid problem matrix via Galerkin projection.
10872 
10873    If the interpolation and restriction operators are the same, uses `MatPtAP()`.
10874    If they are not the same, uses `MatMatMatMult()`.
10875 
10876    Once the coarse grid problem is constructed, correct for interpolation operators
10877    that are not of full rank, which can legitimately happen in the case of non-nested
10878    geometric multigrid.
10879 
10880    Input Parameters:
10881 +  restrct - restriction operator
10882 .  dA - fine grid matrix
10883 .  interpolate - interpolation operator
10884 .  reuse - either `MAT_INITIAL_MATRIX` or `MAT_REUSE_MATRIX`
10885 -  fill - expected fill, use `PETSC_DEFAULT` if you do not have a good estimate
10886 
10887    Output Parameter:
10888 .  A - the Galerkin coarse matrix
10889 
10890    Options Database Key:
10891 .  -pc_mg_galerkin <both,pmat,mat,none> - for what matrices the Galerkin process should be used
10892 
10893    Level: developer
10894 
10895 .seealso: [](chapter_matrices), `Mat`, `MatPtAP()`, `MatMatMatMult()`
10896 @*/
10897 PetscErrorCode MatGalerkin(Mat restrct, Mat dA, Mat interpolate, MatReuse reuse, PetscReal fill, Mat *A)
10898 {
10899   IS  zerorows;
10900   Vec diag;
10901 
10902   PetscFunctionBegin;
10903   PetscCheck(reuse != MAT_INPLACE_MATRIX, PetscObjectComm((PetscObject)A), PETSC_ERR_SUP, "Inplace product not supported");
10904   /* Construct the coarse grid matrix */
10905   if (interpolate == restrct) {
10906     PetscCall(MatPtAP(dA, interpolate, reuse, fill, A));
10907   } else {
10908     PetscCall(MatMatMatMult(restrct, dA, interpolate, reuse, fill, A));
10909   }
10910 
10911   /* If the interpolation matrix is not of full rank, A will have zero rows.
10912      This can legitimately happen in the case of non-nested geometric multigrid.
10913      In that event, we set the rows of the matrix to the rows of the identity,
10914      ignoring the equations (as the RHS will also be zero). */
10915 
10916   PetscCall(MatFindZeroRows(*A, &zerorows));
10917 
10918   if (zerorows != NULL) { /* if there are any zero rows */
10919     PetscCall(MatCreateVecs(*A, &diag, NULL));
10920     PetscCall(MatGetDiagonal(*A, diag));
10921     PetscCall(VecISSet(diag, zerorows, 1.0));
10922     PetscCall(MatDiagonalSet(*A, diag, INSERT_VALUES));
10923     PetscCall(VecDestroy(&diag));
10924     PetscCall(ISDestroy(&zerorows));
10925   }
10926   PetscFunctionReturn(PETSC_SUCCESS);
10927 }
10928 
10929 /*@C
10930     MatSetOperation - Allows user to set a matrix operation for any matrix type
10931 
10932    Logically Collective
10933 
10934     Input Parameters:
10935 +   mat - the matrix
10936 .   op - the name of the operation
10937 -   f - the function that provides the operation
10938 
10939    Level: developer
10940 
10941     Usage:
10942 .vb
10943   extern PetscErrorCode usermult(Mat, Vec, Vec);
10944 
10945   PetscCall(MatCreateXXX(comm, ..., &A));
10946   PetscCall(MatSetOperation(A, MATOP_MULT, (PetscVoidFunction)usermult));
10947 .ve
10948 
10949     Notes:
10950     See the file `include/petscmat.h` for a complete list of matrix
10951     operations, which all have the form MATOP_<OPERATION>, where
10952     <OPERATION> is the name (in all capital letters) of the
10953     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
10954 
10955     All user-provided functions (except for `MATOP_DESTROY`) should have the same calling
10956     sequence as the usual matrix interface routines, since they
10957     are intended to be accessed via the usual matrix interface
10958     routines, e.g.,
10959 .vb
10960   MatMult(Mat, Vec, Vec) -> usermult(Mat, Vec, Vec)
10961 .ve
10962 
10963     In particular each function MUST return `PETSC_SUCCESS` on success and
10964     nonzero on failure.
10965 
10966     This routine is distinct from `MatShellSetOperation()` in that it can be called on any matrix type.
10967 
10968 .seealso: [](chapter_matrices), `Mat`, `MatGetOperation()`, `MatCreateShell()`, `MatShellSetContext()`, `MatShellSetOperation()`
10969 @*/
10970 PetscErrorCode MatSetOperation(Mat mat, MatOperation op, void (*f)(void))
10971 {
10972   PetscFunctionBegin;
10973   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
10974   if (op == MATOP_VIEW && !mat->ops->viewnative && f != (void (*)(void))(mat->ops->view)) mat->ops->viewnative = mat->ops->view;
10975   (((void (**)(void))mat->ops)[op]) = f;
10976   PetscFunctionReturn(PETSC_SUCCESS);
10977 }
10978 
10979 /*@C
10980     MatGetOperation - Gets a matrix operation for any matrix type.
10981 
10982     Not Collective
10983 
10984     Input Parameters:
10985 +   mat - the matrix
10986 -   op - the name of the operation
10987 
10988     Output Parameter:
10989 .   f - the function that provides the operation
10990 
10991     Level: developer
10992 
10993     Usage:
10994 .vb
10995       PetscErrorCode (*usermult)(Mat, Vec, Vec);
10996       MatGetOperation(A, MATOP_MULT, (void (**)(void))&usermult);
10997 .ve
10998 
10999     Notes:
11000     See the file include/petscmat.h for a complete list of matrix
11001     operations, which all have the form MATOP_<OPERATION>, where
11002     <OPERATION> is the name (in all capital letters) of the
11003     user interface routine (e.g., `MatMult()` -> `MATOP_MULT`).
11004 
11005     This routine is distinct from `MatShellGetOperation()` in that it can be called on any matrix type.
11006 
11007 .seealso: [](chapter_matrices), `Mat`, `MatSetOperation()`, `MatCreateShell()`, `MatShellGetContext()`, `MatShellGetOperation()`
11008 @*/
11009 PetscErrorCode MatGetOperation(Mat mat, MatOperation op, void (**f)(void))
11010 {
11011   PetscFunctionBegin;
11012   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11013   *f = (((void (**)(void))mat->ops)[op]);
11014   PetscFunctionReturn(PETSC_SUCCESS);
11015 }
11016 
11017 /*@
11018     MatHasOperation - Determines whether the given matrix supports the particular operation.
11019 
11020    Not Collective
11021 
11022    Input Parameters:
11023 +  mat - the matrix
11024 -  op - the operation, for example, `MATOP_GET_DIAGONAL`
11025 
11026    Output Parameter:
11027 .  has - either `PETSC_TRUE` or `PETSC_FALSE`
11028 
11029    Level: advanced
11030 
11031    Note:
11032    See `MatSetOperation()` for additional discussion on naming convention and usage of `op`.
11033 
11034 .seealso: [](chapter_matrices), `Mat`, `MatCreateShell()`, `MatGetOperation()`, `MatSetOperation()`
11035 @*/
11036 PetscErrorCode MatHasOperation(Mat mat, MatOperation op, PetscBool *has)
11037 {
11038   PetscFunctionBegin;
11039   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11040   PetscValidBoolPointer(has, 3);
11041   if (mat->ops->hasoperation) {
11042     PetscUseTypeMethod(mat, hasoperation, op, has);
11043   } else {
11044     if (((void **)mat->ops)[op]) *has = PETSC_TRUE;
11045     else {
11046       *has = PETSC_FALSE;
11047       if (op == MATOP_CREATE_SUBMATRIX) {
11048         PetscMPIInt size;
11049 
11050         PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)mat), &size));
11051         if (size == 1) PetscCall(MatHasOperation(mat, MATOP_CREATE_SUBMATRICES, has));
11052       }
11053     }
11054   }
11055   PetscFunctionReturn(PETSC_SUCCESS);
11056 }
11057 
11058 /*@
11059     MatHasCongruentLayouts - Determines whether the rows and columns layouts of the matrix are congruent
11060 
11061    Collective
11062 
11063    Input Parameter:
11064 .  mat - the matrix
11065 
11066    Output Parameter:
11067 .  cong - either `PETSC_TRUE` or `PETSC_FALSE`
11068 
11069    Level: beginner
11070 
11071 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatSetSizes()`, `PetscLayout`
11072 @*/
11073 PetscErrorCode MatHasCongruentLayouts(Mat mat, PetscBool *cong)
11074 {
11075   PetscFunctionBegin;
11076   PetscValidHeaderSpecific(mat, MAT_CLASSID, 1);
11077   PetscValidType(mat, 1);
11078   PetscValidBoolPointer(cong, 2);
11079   if (!mat->rmap || !mat->cmap) {
11080     *cong = mat->rmap == mat->cmap ? PETSC_TRUE : PETSC_FALSE;
11081     PetscFunctionReturn(PETSC_SUCCESS);
11082   }
11083   if (mat->congruentlayouts == PETSC_DECIDE) { /* first time we compare rows and cols layouts */
11084     PetscCall(PetscLayoutSetUp(mat->rmap));
11085     PetscCall(PetscLayoutSetUp(mat->cmap));
11086     PetscCall(PetscLayoutCompare(mat->rmap, mat->cmap, cong));
11087     if (*cong) mat->congruentlayouts = 1;
11088     else mat->congruentlayouts = 0;
11089   } else *cong = mat->congruentlayouts ? PETSC_TRUE : PETSC_FALSE;
11090   PetscFunctionReturn(PETSC_SUCCESS);
11091 }
11092 
11093 PetscErrorCode MatSetInf(Mat A)
11094 {
11095   PetscFunctionBegin;
11096   PetscUseTypeMethod(A, setinf);
11097   PetscFunctionReturn(PETSC_SUCCESS);
11098 }
11099 
11100 /*@C
11101    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
11102    and possibly removes small values from the graph structure.
11103 
11104    Collective
11105 
11106    Input Parameters:
11107 +  A - the matrix
11108 .  sym - `PETSC_TRUE` indicates that the graph should be symmetrized
11109 .  scale - `PETSC_TRUE` indicates that the graph edge weights should be symmetrically scaled with the diagonal entry
11110 -  filter - filter value - < 0: does nothing; == 0: removes only 0.0 entries; otherwise: removes entries with abs(entries) <= value
11111 
11112    Output Parameter:
11113 .  graph - the resulting graph
11114 
11115    Level: advanced
11116 
11117 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `PCGAMG`
11118 @*/
11119 PetscErrorCode MatCreateGraph(Mat A, PetscBool sym, PetscBool scale, PetscReal filter, Mat *graph)
11120 {
11121   PetscFunctionBegin;
11122   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11123   PetscValidType(A, 1);
11124   PetscValidLogicalCollectiveBool(A, scale, 3);
11125   PetscValidPointer(graph, 5);
11126   PetscUseTypeMethod(A, creategraph, sym, scale, filter, graph);
11127   PetscFunctionReturn(PETSC_SUCCESS);
11128 }
11129 
11130 /*@
11131   MatEliminateZeros - eliminate the nondiagonal zero entries in place from the nonzero structure of a sparse `Mat` in place,
11132   meaning the same memory is used for the matrix, and no new memory is allocated.
11133 
11134   Collective
11135 
11136   Input Parameter:
11137 . A - the matrix
11138 
11139   Level: intermediate
11140 
11141   Developer Note:
11142   The entries in the sparse matrix data structure are shifted to fill in the unneeded locations in the data. Thus the end
11143   of the arrays in the data structure are unneeded.
11144 
11145 .seealso: [](chapter_matrices), `Mat`, `MatCreate()`, `MatCreateGraph()`, `MatChop()`
11146 @*/
11147 PetscErrorCode MatEliminateZeros(Mat A)
11148 {
11149   PetscFunctionBegin;
11150   PetscValidHeaderSpecific(A, MAT_CLASSID, 1);
11151   PetscUseTypeMethod(A, eliminatezeros);
11152   PetscFunctionReturn(PETSC_SUCCESS);
11153 }
11154